伸展树最重口味题 维修数列

来源:互联网 发布:手机淘宝怎么五星好评 编辑:程序博客网 时间:2024/04/28 23:09

链接 : http://www.lydsy.com/JudgeOnline/problem.php?id=1500

如果都做到这题了,就不多说了

有很多的注意点,代码中有注释

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int inf = ~0u>>2;#define L ch[x][0]#define R ch[x][1]#define KT (ch[ ch[rt][1] ][0])const int maxn = 500010;struct SplayTree {    int sz[maxn];    int ch[maxn][2];    int pre[maxn];    int rt,top,top2;    int que[maxn],ss[maxn];    inline int max(int a,int b) {        return a>b?a:b;    }    inline void down(int x){        if(!x) return ;        if(flip[x]) {            flip[ L ] ^= 1;            flip[ R ] ^= 1;            swap(L,R);            swap(ls[x],rs[x]);            flip[x] = false ;        }        if(same[x]) {//注意防止将0节点赋值            if(L) same[ L ]  = 1;            if(R) same[ R ]  = 1;            if(L)val[ L ]  = val[x];            if(R)val[ R ]  = val[x];            if(L)sum[ L ]  = val[x] * sz[ L ];            if(R)sum[ R ]  = val[x] * sz[ R ];            if(L)mx_sum[L] = ls [ L ] = rs[ L ] = max(val[x],sum[ L ]);            if(R)mx_sum[R] = ls [ R ]  = rs[ R ] = max(val[x],sum[ R ]);            same[x] = false ;        }    }    inline void up(int x){        if(!x) return;if(L) down(L);if(R) down(R);//关键所在,儿子节点的信息必须先down下去,不然有可能得到的mx_sum不是真实的        sz[x] = 1 + sz[ L ] + sz[ R ];        sum[x] = val[x] + sum[L] + sum[R];        ls[x] = max( ls[L] , sum[L] + val[x] + max(ls[R],0));        rs[x] = max( rs[R] , sum[R] + val[x] + max(rs[L],0));        mx_sum[x] = max(rs[L],0) + val[x] + max(ls[R],0);        mx_sum[x] = max(mx_sum[x],max(mx_sum[L],mx_sum[R]));    }    inline void Rotate(int x,int f){        int y=pre[x];        down(y);        down(x);        ch[y][!f] = ch[x][f];        pre[ ch[x][f] ] = y;        pre[x] = pre[y];        if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;        ch[x][f] = y;        pre[y] = x;        up(y);    }    inline void Splay(int x,int goal){//将x旋转到goal的下面        down(x);//防止pre[x]就是目标点,下面的循环就进不去了,x的信息就传不下去了        while(pre[x] != goal){            down(pre[pre[x]]); down(pre[x]);down(x);//在旋转之前需要先下传标记,因为节点的位置可能会发生改变            if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x);            else   {                int y=pre[x],z=pre[y];                int f = (ch[z][0]==y);                if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);                else Rotate(y,f),Rotate(x,f);            }        }        up(x);        if(goal==0) rt=x;    }                    inline void RTO(int k,int goal){//将第k位数旋转到goal的下面        int x=rt;        down(x);        while(sz[ L ]+1 != k) {            if(k < sz[ L ] + 1 ) x=L;            else {                k-=(sz[ L ]+1);                x = R;            }            down(x);        }        Splay(x,goal);    }    inline void Newnode(int &x,int c,int f){        if(top2) x = ss[--top2];        else     x = ++top;           L = R = 0; pre[x]=f;        sz[x] = 1;         val[x] = c;  sum[x] = c;        flip[x] = same[x] = false;        ls[x] = rs[x] = mx_sum[x] = c;    }    inline void build(int &x,int l,int r,int f){        if(l>r) return ;        int m=l+r>>1;        Newnode(x,num[m],f);        build(L , l , m-1 , x);        build(R , m+1 , r , x);        pre[x]=f;        up(x);    }    inline void debug(){        vist(rt);puts("");    }    inline void init(int n){        ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;        rt=top=top2=0;         flip[0]=false;   val[0]=0; sum[0]=0; same[0] = false;        ls[0] = rs[0] = mx_sum[0] = -inf;        for(int i = 1 ; i <= n ; i++)  scanf("%d" , &num[i]);        Newnode(rt,-inf,0);        Newnode(ch[rt][1],-inf,rt);        sz[rt]=2;        build(KT,1,n,ch[rt][1]);        up(ch[rt][1]);        up(rt);    }    inline void erase(int x) {//把以x为祖先结点删掉放进内存池,回收内存        int father = pre[x];        int head = 0 , tail = 0;        for (que[tail++] = x ; head < tail ; head ++) {            ss[top2 ++] = que[head];            if(ch[ que[head] ][0]) que[tail++] = ch[ que[head] ][0];            if(ch[ que[head] ][1]) que[tail++] = ch[ que[head] ][1];        }        ch[ father ][ ch[father][1] == x ] = 0;        up(father);    }    void vist(int x){        if(x){            printf("结点%2d : 左儿子  %2d   右儿子  %2d    val : %5d  mxsum : %5d    flip :  %5d  same : %d\n",x,            L,R,val[x],mx_sum[x],flip[x],same[x]);            vist(L);            vist(R);        }    }    inline void GET_SUM() {         scanf("%d%d",&pos,&tot);         int l=pos,r=pos+tot-1;         RTO(l,0);         RTO(r+2,rt);         printf("%d\n",sum[KT]);    }    inline void DELETE()  {         scanf("%d%d",&pos,&tot);         int l=pos,r=tot+pos-1;         RTO(l,0);         RTO(r+2,rt);         erase(KT);         KT=0;         up(ch[rt][1]);         up(rt);    }    inline void INSERT()  {        scanf("%d%d",&pos,&tot);        for(int i=1;i<=tot;i++)    scanf("%d",&num[i]);        RTO(pos+1,0);        RTO(pos+2,rt);        build(KT,1,tot,ch[rt][1]);        up(ch[rt][1]);    up(rt);    }    inline void MAKE_SAME() {        int c;        scanf("%d%d%d",&pos,&tot,&c);        int l=pos,r=pos+tot-1;        RTO(l,0);        RTO(r+2,rt);        same[KT] = true;        val[KT] = c;        sum[KT] = sz[KT] * c;        mx_sum[KT] = max( c , sum[KT] );        ls[KT] = max(c , sum[KT]);        rs[KT] = max(c , sum[KT]);        up(ch[rt][1]);        up(rt);    }    void print(int x) {        if(x) {            down(x);            print(L);            if(val[x]>-10000) {                if(flag) printf(" ");                printf("%d",val[x]);                flag=1;            }            print(R);        }    }    inline void OUT() {        flag=0;        print(rt);        printf("\n");    }    inline void REVERSE() {        scanf("%d%d",&pos,&tot);        int l=pos,r=pos+tot-1;        RTO(l,0);        RTO(r+2,rt);        flip[KT]^=1;    }inline void MAX_SUM() {         RTO(1,0) ;         RTO(sz[rt],rt);         printf("%d\n",mx_sum[KT]);    }    int flag;    int pos,tot;    bool flip[maxn];    int val[maxn];    int num[maxn];    int sum[maxn];//求和    bool same[maxn];//统一修改为一个数    int ls[maxn];//最大前缀和    int rs[maxn];//最大后缀和    int mx_sum[maxn];//最大子列和}spt;int main(){    int n,m,pos,tot;    scanf("%d%d",&n,&m);    spt.init(n);    char op[50];    while(m--) {        scanf("%s",op);        if(strcmp(op,"GET-SUM") == 0) {            spt.GET_SUM();        }  else if(strcmp(op,"MAX-SUM") == 0) {            spt.MAX_SUM();        }  else if(strcmp(op,"INSERT") == 0) {            spt.INSERT();        }  else if(strcmp(op,"DELETE") == 0) {            spt.DELETE();        }  else if(strcmp(op,"MAKE-SAME") == 0) {            spt.MAKE_SAME();        }  else if(strcmp(op,"OUT") == 0) {            spt.OUT();        }  else if(strcmp(op,"DEBUG") == 0){            spt.debug();        }  else if(strcmp(op,"NEWTREE")==0){            spt.debug();        }  else {            spt.REVERSE();        }    }    return 0;}


原创粉丝点击