杭电多校第八场 Taotao Picks Apples(线段树)

  • Post author:
  • Post category:其他



Taotao Picks Apples




Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 1862    Accepted Submission(s): 580


Problem Description

There is an apple tree in front of Taotao’s house. When autumn comes,

n

apples on the tree ripen, and Taotao will go to pick these apples.

When Taotao picks apples, Taotao scans these apples from the first one to the last one. If the current apple is the first apple, or it is strictly higher than the previously picked one, then Taotao will pick this apple; otherwise, he will not pick.

Given the heights of these apples

h

1,

h

2,⋯,

h


n

, you are required to answer some independent queries. Each query is two integers

p

,

q

, which asks the number of apples Taotao would pick, if the height of the

p

-th apple were

q

(instead of

h


p

). Can you answer all these queries?

Input

The first line of input is a single line of integer

T

(1≤

T

≤10), the number of test cases.

Each test case begins with a line of two integers

n

,

m

(1≤

n

,

m

≤105), denoting the number of apples and the number of queries. It is then followed by a single line of

n

integers

h

1,

h

2,⋯,

h


n

(1≤

h


i

≤109), denoting the heights of the apples. The next

m

lines give the queries. Each of these

m

lines contains two integers

p

(1≤

p



n

) and

q

(1≤

q

≤109), as described in the problem statement.

Output

For each query, display the answer in a single line.

Sample Input

1 5 3 1 2 3 4 4 1 5 5 5 2 3

Sample Output

1 5 3




Hint


For the first query, the heights of the apples were 5, 2, 3, 4, 4, so Taotao would only pick the first apple. For the second query, the heights of the apples were 1, 2, 3, 4, 5, so Taotao would pick all these five apples. For the third query, the heights of the apples were 1, 3, 3, 4, 4, so Taotao would pick the first, the second and the fourth apples.

Source


2018 Multi-University Training Contest 8

思路:一开始读错题了,以为是找从第一个数开始的最长上升子序列,到最后才发现是遇到一个比上一个大的就摘掉,线段树解法是先预处理出来两个数组d1,d2,d1[i]数组里存的是从第1到a[i]能摘的苹果,这个比较好处理,d2[i]数组里存的是从a[i]到a[n]能摘的苹果,这个稍微麻烦些,倒着遍历,每次用线段树找出a[i]之后第一个比第a[i]这个数大的的位置j,d2[i] = d2[j] + 1,每次修改查询,用线段树找出1到p-1最大的数的位置pos,ans+=d1[pos],如果q比a[pos]大的话,ans再加1,再用线段树找出p+1到n第一个比max(a[pos],q )大的数的位置pos2,ans+=d2[pos2]

#include <bits/stdc++.h>
#define MAXN 100005
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
struct node
{
    int l,r;
    int Max,pos;
}tree[MAXN << 2];
int a[MAXN],d1[MAXN],d2[MAXN];
int cur;
void pushup(int num)
{
    tree[num].Max = max(tree[lson].Max,tree[rson].Max);
    if(tree[lson].Max >= tree[rson].Max) tree[num].pos = tree[lson].pos;
    else tree[num].pos = tree[rson].pos;
}
void build(int num,int l,int r) 
{
    tree[num].l = l;
    tree[num].r = r;
    if(l == r) {
        tree[num].Max = a[l];
        tree[num].pos = l;
        return;
    }
    int mid = (l + r) >> 1;
    build(lson,l,mid);
    build(rson,mid + 1,r);
    pushup(num);
}
void query1(int num,int l,int r,int val)
{
    if(tree[num].l == tree[num].r) {
        if(tree[num].Max > val) cur = min(cur,tree[num].l);
        return;
    }
    int mid = (tree[num].l + tree[num].r) >> 1;
    if(tree[num].l == l && tree[num].r == r) {
        if(tree[lson].Max > val) query1(lson,l,mid,val);
        else if(tree[rson].Max > val) query1(rson,mid + 1,r,val);
        return;
    }
    if(r <= mid) query1(lson,l,r,val);
    else if(l > mid) query1(rson,l,r,val);
    else {
        query1(lson,l,mid,val);
        query1(rson,mid + 1,r,val);
    }
}
void query2(int num,int l,int r)
{
    if(tree[num].l == l && tree[num].r == r) {
        if(tree[num].Max > a[cur]) cur = tree[num].pos;
        return;
    }
    int mid = (tree[num].l + tree[num].r) >> 1;
    if(r <= mid) query2(lson,l,r);
    else if(l > mid) query2(rson,l,r);
    else {
        query2(lson,l,mid);
        query2(rson,mid + 1,r);
    }
}
int main(void)
{
    int T,n,m,Max,pos,val,ans;
    scanf("%d",&T);
    while(T--) {
        memset(d1,0,sizeof(d1));
        memset(d2,0,sizeof(d2));
        scanf("%d %d",&n,&m);
        Max = 0;
        for(int i = 1; i <= n; i++) {
            scanf("%d",&a[i]);
            if(a[i] > Max) {
                d1[i] = d1[i - 1] + 1; 
                Max = a[i];
            }
            else d1[i] = d1[i - 1];
        }
        build(1,1,n);
        d2[n] = 1;
        for(int i = n - 1; i >= 1; i--) {
            cur = n + 1;
            query1(1,i + 1,n,a[i]);
            d2[i] = d2[cur] + 1;
        }
        while(m--) {
            ans = cur = 0;
            scanf("%d %d",&pos,&val);
            if(pos != 1) query2(1,1,pos - 1);
            ans += d1[cur];
            if(val > a[cur]) ans++;
            else val = a[cur];
            cur = n + 1;
            if(pos != n) query1(1,pos + 1,n,val);
            ans += d2[cur];
            printf("%d\n",ans);
        } 
    }
    return 0;
}
/*
1
5 3
1 2 3 4 4
1 5
5 5
2 3
*/



版权声明:本文为GYH0730原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。