• 【BZOJ】1251: 序列终结者


    【题意】给定含有n个0的的数列。

    1.区间加值

    2.区间翻转

    3.区间求最大值

    【算法】平衡树(fhq-treap)

    需要特别注意的是:

    1.使0点对全局无影响并全程保持(例如求max,t[0].mx=-inf)

    2.平衡树和线段树的上传区别在于要考虑本身这个点。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=100010;
    struct tree{int l,r,rnd,num,mx,add,delta,sz;}t[maxn*2];
    int st[maxn];
    int n,m,root;
    void down(int k){
        if(t[k].delta){
            swap(t[k].l,t[k].r);
            if(t[k].l)t[t[k].l].delta^=1;
            if(t[k].r)t[t[k].r].delta^=1;
            t[k].delta=0;
        }
        if(t[k].add){
            int p=t[k].add;
            if(t[k].l)t[t[k].l].add+=p,t[t[k].l].mx+=p,t[t[k].l].num+=p;
            if(t[k].r)t[t[k].r].add+=p,t[t[k].r].mx+=p,t[t[k].r].num+=p;//keep 0->0!!!
            t[k].add=0;
        }
    }
    int max(int a,int b){return a<b?b:a;}
    void up(int k){//different from sgt!
        t[k].mx=max(t[k].num,max(t[t[k].l].mx,t[t[k].r].mx));
        t[k].sz=1+t[t[k].l].sz+t[t[k].r].sz;
    }
    void dfs(int k){
        if(!k)return;
        dfs(t[k].l);
        dfs(t[k].r);
        up(k);
    }
    void build(){
        int top=0;
        for(int i=1;i<=n;i++){
            t[i]=(tree){0,0,rand(),0,0,0,0,1};
            while(top&&t[st[top]].rnd>t[i].rnd){
                t[st[top]].r=t[i].l;
                t[i].l=st[top--];
            }
            t[st[top]].r=i;
            st[++top]=i;
        }
        dfs(st[1]);
        t[0].r=0;
        t[0].mx=-0x3f3f3f3f;//make 0 no influence
        root=st[1];
    }
    int merge(int a,int b){
        if(!a||!b)return a^b;
        if(t[a].rnd<t[b].rnd){
            down(a);
            t[a].r=merge(t[a].r,b);
            up(a);
            return a;
        }
        else{
            down(b);
            t[b].l=merge(a,t[b].l);
            up(b);
            return b;
        }
    }
    void split(int k,int &l,int &r,int x){
        if(!k)return void(l=r=0);
        down(k);
        if(x<t[t[k].l].sz+1){
            r=k;
            split(t[k].l,l,t[k].l,x);
        }
        else{
            l=k;
            split(t[k].r,t[k].r,r,x-t[t[k].l].sz-1);
        }
        up(k);
    }
    void plus(int l,int r,int x){
        int a,b,c;
        split(root,b,c,r);
        split(b,a,b,l-1);
        t[b].add+=x;t[b].mx+=x;t[b].num+=x;
        root=merge(a,b);root=merge(root,c);
    }
    void turn(int l,int r){
        int a,b,c;
        split(root,b,c,r);split(b,a,b,l-1);
        t[b].delta^=1;
        root=merge(a,b);root=merge(root,c);
    }
    int ask(int l,int r){
        int a,b,c,ans;
        split(root,b,c,r);split(b,a,b,l-1);
        ans=t[b].mx;
        root=merge(a,b);root=merge(root,c);
        return ans;
    }
    int main(){
        srand(233);
        scanf("%d%d",&n,&m);
        build();
        for(int i=1;i<=m;i++){
            int k,l,r,x;
            scanf("%d%d%d",&k,&l,&r);
            if(l>r)continue;
            if(k==1){
                scanf("%d",&x);
                plus(l,r,x);
            }
            else if(k==2)turn(l,r);
            else printf("%d
    ",ask(l,r));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Django ORM中常用的字段类型以及参数配置
    python enumerate用法总结
    Django 模板渲染
    Django null=True和blank=True的区别
    Django下关于session的使用
    方程组法求函数的解析式
    求数列通项公式的小众方法
    不等式性质
    多项选择题
    对勾型函数
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7892394.html
Copyright © 2020-2023  润新知