• HDU


    题意:数量为N的序列a和b,a初始全为0,b为给定的1-N的排列。有两种操作:1.将a序列区间[L,R]中的数全部+1;2.查询区间[L,R]中的 ai/bi⌋(向下取整)

    分析:对于一个位置i,如果ai<bi,那么该位置不能对结果做出贡献;而当某一次操作后,ai>=bi了,就对结果的贡献值+1。那么可以用在线段树的结点中维护每个区间的最大a和最小b,和已经产生的贡献cnt。如果一个区间中最大的a超过了b,那么就说明此次更新操作使该区间的结果产生了变化,那么就要向下找到那个产生贡献的位置。当更新完结果值以后,就将这个位置上的bi再加上bi(由于结果要求向下取整),那么相当于这个位置的ai又要重新更新bi次才能再次产生贡献。

    所以,update函数中,如果出现a>=b的情况,那么我们必须递归到最底层找到出现;如果a<b,那么只要打上延迟标记即可。

    #include<bits/stdc++.h>
    #define Lson rt<<1,l,m
    #define Rson rt<<1|1,m+1,r
    using namespace std;
    typedef long long LL;
    const int maxn =1e5+5;
    struct Node{
        int cnt,addv,maxa,minb;
    }tree[maxn<<2];
    int b[maxn];
    void pushup(int rt)
    {
        tree[rt].cnt = tree[rt<<1].cnt+tree[rt<<1|1].cnt;
        tree[rt].maxa = max(tree[rt<<1].maxa,tree[rt<<1|1].maxa);
        tree[rt].minb = min(tree[rt<<1].minb,tree[rt<<1|1].minb);
    }
    void pushdown(int rt)
    {
        if(tree[rt].addv){
            int v=tree[rt].addv;
            tree[rt].addv=0;
            tree[rt<<1].maxa+=v;
            tree[rt<<1|1].maxa+=v;
            tree[rt<<1].addv+=v;
            tree[rt<<1|1].addv+=v;
        }
    }
    void build(int rt,int l,int r)
    {
        tree[rt].addv=0;
        if(l==r){
            tree[rt].cnt = tree[rt].maxa = 0;
            tree[rt].minb = b[l];
            return;
        }
        int m = (l+r)>>1;
        build(Lson);
        build(Rson);
        pushup(rt);
    }
    void update(int rt,int l,int r,int L,int R)
    {
        if(L<=l && R>=r){
            tree[rt].maxa++;
            if(tree[rt].maxa<tree[rt].minb){    //还没有元素做出贡献
                tree[rt].addv++;
                return;
            }
            else if(l==r){
                tree[rt].cnt++;
                tree[rt].minb+=b[l];
                return;
            }
        }
        pushdown(rt);
        int m = (l+r)>>1;
        if(L<=m)update(Lson,L,R);
        if(R>m)update(Rson,L,R);
        pushup(rt);
    }
    
    int query(int rt,int l,int r,int L,int R)
    {
        if(L<=l&&R>=r) return tree[rt].cnt;
        int m =(l+r)>>1;
        pushdown(rt);
        int ans=0;
        if(L<=m) ans+=query(Lson,L,R);
        if(R>m) ans+=query(Rson,L,R);
        return ans;
    }  
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int T,N,M,u,v,tmp;
        while(scanf("%d%d",&N,&M)==2){
            for(int i=1;i<=N;++i)  scanf("%d",&b[i]);
            build(1,1,N);
            char op[8];
            int L,R;
            while(M--){
                scanf("%s %d %d",op,&L,&R);
                if(op[0]=='a') update(1,1,N,L,R);
                else printf("%d
    ",query(1,1,N,L,R));
            }
        }
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    句子反转
    python中计时模块timeit的使用方法
    python入门(一)
    将小程序的API封装成支持Promise的API
    微信小程序实现导航功能的操作步骤
    微信小程序朋友转发和朋友圈分享
    js原生上传图片
    FormData
    原生 websocket
    判断手机终端是pc还是移动端,并自动跳转
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9373911.html
Copyright © 2020-2023  润新知