zoukankan      html  css  js  c++  java
  • 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;
    }
     
  • 相关阅读:
    mongoDB使用
    mac环境下mongodb的安装和使用
    statrc部分
    权限部分
    在Linux 安装Python3.5.6详细文档!!!!
    linux回顾
    linux服务配置
    路飞ORM练习
    考试题-路飞中期(卷一)
    git hub命令,上传到github
  • 原文地址:https://www.cnblogs.com/Draymonder/p/9535550.html
Copyright © 2011-2022 走看看