HDU6406 Taotao Picks Apples

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 h1, h2, …, hn, 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 hp). 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 h1, h2, …, hn (1 ≤ hi ≤ 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.

Example Input

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

Example Output

1
5
3

题意

给你一个序列,序列的第一个数必取,从前往后,当碰到比前一个数严格大于的数就选取。M次修改序列中的值,问修改后的序列能选取的个数。询问不叠加。

题解

首先,根据题意,我们可以建立一颗线段树,维护区间的最大值mx和能选取的长度len,
问题就在于两个区间如何合并。
HDU6406.png
当我们合并根节点rt时,能选取的长度len[rt]=len[L]+右区间能选取的长度,我们通过二分搜索右区间来解决。

  • 当发现rls区间的最大值mx[rls]<=mx[L],显然,应该直接忽略rls,搜索rrs;
  • 当发现rls区间的最大值mx[rls]>mx[L],此时,rls必有可选的元素,且此时区间最大值mx会等于mx[rls],则右区间rrs可选的长度不变,为len[r]-len[rls];
  • 当递归区间l==r时,我们判断mx[L]跟当前元素的关系。

C++

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<stack>

using namespace std;

const int N = 1e5 + 50;

int mx[N * 4], len[N * 4], n, m, a[N], T;

int dfs(int p, int l, int r, int v)
{
    if (l == r) return v < mx[p];
    else if (mx[p << 1] <= v) return dfs(p << 1 | 1, ((l + r) >> 1) + 1, r, v);
    else
        return dfs(p << 1, l, (l + r) >> 1, v) + len[p] - len[p << 1];
}

void build(int p, int l, int r)
{
    if (l == r)
    {
        mx[p] = a[l];
        len[p] = 1;
        return ;
    }
    int m = (l + r) >> 1;
    build(p << 1, l, m);
    build(p << 1 | 1, m + 1, r);

    mx[p] = max(mx[p << 1], mx[p << 1 | 1]);
    len[p] = len[p << 1] + dfs(p << 1 | 1, m + 1, r, mx[p << 1]);
}


void update(int p, int l, int r, int x, int v)
{
    if (l == r)
    {
        mx[p] = v;
        return ;
    }

    int m = (l + r) >> 1;

    if (x <= m) update(p << 1, l, m, x, v);
    else
        update(p << 1 | 1, m + 1, r, x, v);

    mx[p] = max(mx[p << 1], mx[p << 1 | 1]);
    len[p] = len[p << 1] + dfs(p << 1 | 1, m + 1, r, mx[p << 1]);

}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("r.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);

    for (cin >> T; T--;)
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i++) cin >> a[i];
        build(1, 1, n);

        for (int x, v, i = 1; i <= m; i++)
        {
            cin >> x >> v;
            update(1, 1, n, x, v);
            cout << len[1] << endl;
            update(1, 1, n, x, a[x]);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值