hdu 6406 Taotao Picks Apples 线段树 单点更新

Taotao Picks Apples

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2506    Accepted Submission(s): 786


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 (1T10), the number of test cases.

Each test case begins with a line of two integers n,m (1n,m105), denoting the number of apples and the number of queries. It is then followed by a single line of n integers h1,h2,,hn (1hi109), denoting the heights of the apples. The next m lines give the queries. Each of these m lines contains two integers p (1pn) and q (1q109), as described in the problem statement.
 
Output
For each query, display the answer in a single line.
 

给你长度为n的序列, 然后从位置1,寻找单调栈的最大长度

然后修改 v[pos] = val, 再求 单调栈的最大长度

但是队友说是单调栈 ,我就用线段树维护了个单调栈,但是我维护的好像有些SB,就是每次左区间的最大值+(用单调栈跑一次最大长度)

然后完美的T了 ,然后就没管这道题了

后来看了一个人的题解,是这样子分析的

对于每一个区间, 贡献只能从左区间  + 右区间的部分选择

然后 考虑: 两种情况 ,如果 右区间的最大值 <= 左区间最大值,那么右区间肯定没有贡献,为0

然后考虑 :如果右区间的最大值 >  左区间最大值,那么问题可以递归 右区间的左儿子 和 右儿子的情况

这样的复杂度 大概是T*m*logn*logn (单点更新val值一个log  然后每次 合并区间的时候又要一个log)

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5+10;
#define ls rt<<1
#define rs rt<<1|1

int mx[N<<2],cnt[N<<2];

int query(int rt,int l,int r,int v) {
    if(l==r) return mx[rt] > v;
    if(mx[rt] <= v) return 0;
    int m = (l+r)>>1;
    if(mx[ls] <= v) return query(rs,m+1,r,v);
    else return cnt[rt]-cnt[ls]+query(ls,l,m,v);
}
int n,m,v[N];
void build(int rt,int l,int r) {
    mx[rt] = cnt[rt] =0;
    if(l == r) {
        mx[rt]=v[l]; cnt[rt]=1;
        return ;
    }
    int m=(l+r)>>1;
    build(ls,l,m);
    build(rs,m+1,r);
    mx[rt]=max(mx[ls], mx[rs]);
    cnt[rt] = cnt[ls] + query(rs,m+1,r,mx[ls]);
}

void update(int rt,int l,int r,int pos,int val) {
    if(l==r && l == pos) {
        mx[rt]=val;
        cnt[rt] = 1;
        return ;
    }
    int m = (l+r)>>1;
    if(pos <= m)
        update(ls,l,m,pos,val);
    else
        update(rs,m+1,r,pos,val);
    mx[rt]=max(mx[ls], mx[rs]);
    cnt[rt] = cnt[ls] + query(rs,m+1,r,mx[ls]);
}

int main() {
    //freopen("in.txt","r",stdin);
    int T; scanf("%d",&T);
    while (T--) {
        scanf("%d %d", &n, &m);
        for(int i=1;i<=n;i++)
            scanf("%d",&v[i]);
        build(1,1,n);
        while (m--) {
            int pos, val;
            scanf("%d %d",&pos,&val);
            //pos位置 更新成val
            update(1,1,n,pos,val);
            printf("%d
",cnt[1]);
            //还原
            update(1,1,n,pos,v[pos]);
        }
    }
    return 0;
}
 
原文地址:https://www.cnblogs.com/Draymonder/p/9535550.html