zoukankan      html  css  js  c++  java
  • poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)

      好题。我做了很久,学了大牛们的区间搬移。主要的代码都有注释。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define INF 999999999
    #define key_value ch[ch[root][1]][0]
    using namespace std;
    const int MAXN = 200010;
    int pre[MAXN],lazy[MAXN],siz[MAXN],ch[MAXN][2],s[MAXN],key[MAXN],tot1,tot2,root,ans[MAXN];
    int n,a[MAXN],rev[MAXN];//rev表示旋转 lazy标记增加的量
    /****************************/
    void Treavel(int x)
    {
        if(x)
        {
            Treavel(ch[x][0]);
            printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d lazy=%2d rev=%2d ans=%2d
    ",x,ch[x][0],ch[x][1],pre[x],siz[x],key[x],lazy[x],rev[x],ans[x]);
            Treavel(ch[x][1]);
        }
    }
    void debug()
    {
        printf("root:%d
    ",root);
        Treavel(root);
    }
    /****************************/
    void Newnode(int &rt,int pa,int k)
    {
        if(tot2)
            rt = s[--tot2];
        else
            rt = ++tot1;
        pre[rt] = pa;
        key[rt] = k;
        lazy[rt] = 0;
        siz[rt] = 1;
        rev[rt] = 0;
        ans[rt] = k;
        ch[rt][0] = ch[rt][1] = 0;
    }
    void pushup(int rt)
    {
        siz[rt] = siz[ch[rt][0]] + siz[ch[rt][1]] + 1;
        ans[rt] = key[rt];
        if(ch[rt][0]) //因为是min
            ans[rt] = min(ans[rt],ans[ch[rt][0]]);
        if(ch[rt][1]) 
            ans[rt] = min(ans[rt],ans[ch[rt][1]]);
    }
    void pushdown(int rt)
    {
        if(rev[rt]){
            rev[ch[rt][0]] ^= 1;
            rev[ch[rt][1]] ^= 1;
            swap(ch[rt][0],ch[rt][1]);
            rev[rt] = 0;
        }
        if(lazy[rt]){
            lazy[ch[rt][0]] += lazy[rt];
            lazy[ch[rt][1]] += lazy[rt];
            key[ch[rt][0]] += lazy[rt];
            key[ch[rt][1]] += lazy[rt];
            ans[ch[rt][0]] += lazy[rt];
            ans[ch[rt][1]] += lazy[rt];
            lazy[rt] = 0;
        }
    }
    void build(int &rt,int l,int r,int pa)
    {
        if(l > r)
            return ;
        int m = (l+r)/2;
        Newnode(rt,pa,a[m]);
        build(ch[rt][0],l,m-1,rt);
        build(ch[rt][1],m+1,r,rt);
        pushup(rt);
    }
    void Init()
    {
        tot1 = tot2 = root = 0;
        siz[root] = pre[root] = lazy[root] = key[root] = rev[root] = 0;
        ans[root] = INF;
        ch[root][0] = ch[root][1] = 0;
        Newnode(root,0,-1);
        Newnode(ch[root][1],root,-1);
        build(key_value,1,n,ch[root][1]);
        pushup(ch[root][1]);
        pushup(root);
    }
    //先pushdown将lazy压下去
    void Rotate(int rt,int kind)
    {
        pushdown(pre[rt]);
        pushdown(rt);
        int y = pre[rt];
        ch[y][!kind] = ch[rt][kind];
        pre[ch[rt][kind]] = y;
        if(pre[y]){
            ch[pre[y]][ch[pre[y]][1]==y] = rt;
        }
        pre[rt] = pre[y];
        ch[rt][kind] = y;
        pre[y] = rt;
        pushup(y);
        pushup(rt);
    }
    //先pushdown将lazy压下去
    void splay(int rt,int goal)
    {
        pushdown(rt);
        while(pre[rt] != goal)
        {
            if(pre[pre[rt]] == goal){
                pushdown(pre[rt]);
                pushdown(rt);
                Rotate(rt,ch[pre[rt]][0]==rt);
            }
            else {
                pushdown(pre[pre[rt]]);
                pushdown(pre[rt]);
                pushdown(rt);
                int y = pre[rt];
                int kind = ch[pre[y]][0]==y;
                if(ch[y][kind] == rt){
                    Rotate(rt,!kind);
                    Rotate(rt,kind);
                }
                else {
                    Rotate(y,kind);
                    Rotate(rt,kind);
                }
            }
        }
        pushup(rt);
        if(goal == 0)
            root = rt;
    
    }
    int Get_kth(int rt,int k)
    {
        pushdown(rt);
        int t = siz[ch[rt][0]] + 1;
        if(t == k)
            return rt;
        else if(t > k){
            return Get_kth(ch[rt][0],k);
        }
        else {
            return Get_kth(ch[rt][1],k-t);
        }
        pushup(rt);
    }
    void add(int x,int y,int z)
    {
        splay(Get_kth(root,x),0);
        splay(Get_kth(root,y+2),root);
        lazy[key_value] += z;
        key[key_value] += z;
        ans[key_value] += z;
        pushup(ch[root][1]);
        pushup(root);//
    }
    int Get_min(int rt)
    {
        pushdown(rt);
        while(ch[rt][0]){
            rt = ch[rt][0];
            pushdown(rt);
        }
        return rt;
    }
    int Get_max(int rt)
    {
        pushdown(rt);
        while(ch[rt][1]){
            rt = ch[rt][1];
            pushdown(rt);
        }
        return rt;
    }
    int query(int x,int y)
    {
        splay(Get_kth(root,x),0);
        splay(Get_kth(root,y+2),root);
        return ans[key_value];
    }
    void Del(int x)
    {
        splay(Get_kth(root,x),0);
        splay(Get_kth(root,x+2),root);
        pre[key_value] = 0;
        key_value = 0;
        pushup(ch[root][1]);
        pushup(root);
    }
    void Insert(int x,int y)
    {
        splay(Get_kth(root,x+1),0);
        splay(Get_kth(root,x+2),root);
        Newnode(key_value,ch[root][1],y);
        pushup(ch[root][1]);
        pushup(root);
    }
    void Reverse(int x,int y)
    {
        splay(Get_kth(root,x),0);
        splay(Get_kth(root,y+2),root);
        rev[key_value] ^= 1;
        pushup(ch[root][1]);
        pushup(root);
    }
    void Revolve(int l,int r,int t)
    {
        //区间平移其实就是把区间[l,c-1],[c,r]中的[c,r]放到[l,c-1]前
        int len = r - l + 1;//取mod
        t = (t%len + len)%len;
        if(!t)return ;
        int c = r - t + 1;
        splay(Get_kth(root,c),0);
        splay(Get_kth(root,r+2),root);
        int tmp = key_value;//这里的是[c,r]的区间
        key_value = 0;
        pushup(ch[root][1]);
        pushup(root);//注意这两步 这里把key_value取0 这样主要为了取走[c,r],所以要更新
        splay(Get_kth(root,l),0);
        splay(Get_kth(root,l+1),root);
        key_value = tmp;
        pre[key_value] = ch[root][1];
        pushup(ch[root][1]);
        pushup(root);
    }
    int main()
    {
        int i,j;
        while(~scanf("%d",&n))
        {
            for(i=1; i<=n; i++){
                scanf("%d",&a[i]);
            }
            Init();
            int q;
            scanf("%d",&q);
            char work[10];
            //debug();
            //cout<<"test: "<<endl;
            while(q--)
            {
                scanf("%s",work);
                if(work[0] == 'A'){
                    int x,y,z;
                    scanf("%d%d%d",&x,&y,&z);
                    add(x,y,z);
                    //debug();
                }
                else if(work[0] == 'M'){
                    int x,y;
                    scanf("%d%d",&x,&y);
                    printf("%d
    ",query(x,y));
                }
                else if(work[0] == 'D'){
                    int x;
                    scanf("%d",&x);
                    Del(x);
                    //debug();
                }
                else if(work[0] == 'I'){
                    int x,y;
                    scanf("%d%d",&x,&y);
                    Insert(x,y);
                    //debug();
                }
                else if(strcmp(work,"REVERSE") == 0){
                    int x,y;
                    scanf("%d%d",&x,&y);
                    Reverse(x,y);
                    //debug();
                }
                else if(strcmp(work,"REVOLVE") == 0){
                    int x,y,ft;
                    scanf("%d%d%d",&x,&y,&ft);
                    Revolve(x,y,ft);
                    //debug();
                }
            }
        }
    }
    
  • 相关阅读:
    Golang Failpoint 的设计与实现
    没涉及到最值求解;观点:矩阵乘法无法表达出结果。 现实生活中事件、现象的数学表达
    多元微分学 枚举破解15位路由器密码 存储空间限制 拆分减长,求最值 数据去重
    ARP Poisoning Attack and Mitigation Techniques ARP欺骗 中间人攻击 Man-In-The-Middle (MITM) attack 嗅探 防范 Can one MAC address have two different IP addresses within the network?
    The C10K problem
    HTTP Streaming Architecture HLS 直播点播 HTTP流架构
    现代IM系统中消息推送和存储架构的实现
    现代IM系统中的消息系统架构
    长连接锁服务优化实践 C10K问题 nodejs的内部构造 limits.conf文件修改 sysctl.conf文件修改
    doubleclick cookie、动态脚本、用户画像、用户行为分析和海量数据存取 推荐词 京东 电商 信息上传 黑洞 https://blackhole.m.jd.com/getinfo
  • 原文地址:https://www.cnblogs.com/sweat123/p/5140362.html
Copyright © 2011-2022 走看看