一些数据结构题目的代码片段

来源:互联网 发布:linux 查看文件夹用户 编辑:程序博客网 时间:2024/06/06 08:26

  自从暑假洗心革面怒艹数据结构以来,从我手中通过的题,其代码量就基本没低于100行……到现在虽然还有很多题不会搞,却也可以简单地写一些东西,并整理出个可堪一用的板子了。接下来提到的基本是各种树形数据结构的入门级题目和提高级题目,绝大多数来自Damocles数据结构专题训练,主要给队友参考吧。

  HDU1754

  难度一颗星;单点替换,区间最值。树状数组、线段树、Splay各一发。

#include<cstdio>#include<algorithm>using namespace std;const int MAXN=200005;int bit[MAXN],num[MAXN],n;inline int lowbit(int x) {    return x&-x;}void modify(int x,int val) {    num[x]=val;    for(int i=x; i<=n; i+=lowbit(i)) {        bit[i]=max(bit[i],val);        for(int j=1; j<lowbit(i); j<<=1)            bit[i]=max(bit[i],bit[i-j]);    }}int query(int L,int R) {    int ret=num[R];    while(true) {        ret=max(ret,num[R]);        if(L==R)            break;        for(R-=1; R-L>=lowbit(R); R-=lowbit(R))            ret=max(ret,bit[R]);    }    return ret;}int main() {    int q,a,b;    char op;    while(~scanf("%d%d",&n,&q)) {        memset(bit,0,sizeof(bit));        for(int i=1; i<=n; ++i) {            scanf("%d",&b);            modify(i,b);        }        while(q--) {            scanf(" %c%d%d",&op,&a,&b);            switch(op) {            case 'Q':                printf("%d\n",query(a,b));                break;            case 'U':                modify(a,b);                break;            }        }    }}
#include<cstdio>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int MAXN=200005;int maxv[MAXN<<2];void PushUp(int rt) {    maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);}void build(int l,int r,int rt) {    if(l==r) {        scanf("%d",&maxv[rt]);        return;    }    int m=l+r>>1;    build(lson);    build(rson);    PushUp(rt);}void update(int p,int val,int l,int r,int rt) {    if(l==r) {        maxv[rt]=val;        return;    }    int m=l+r>>1;    if(p<=m)        update(p,val,lson);    else        update(p,val,rson);    PushUp(rt);}int query(int L,int R,int l,int r,int rt) {    if(L<=l&&r<=R)        return maxv[rt];    int m=l+r>>1,ret=0;    if(L<=m)        ret=max(ret,query(L,R,lson));    if(m<R)        ret=max(ret,query(L,R,rson));    return ret;}int main() {    int n,q,a,b;    char op;    while(~scanf("%d%d",&n,&q)) {        build(1,n,1);        while(q--) {            scanf(" %c%d%d",&op,&a,&b);            switch(op) {            case 'Q':                printf("%d\n",query(a,b,1,n,1));                break;            case 'U':                update(a,b,1,n,1);                break;            }        }    }}
#include<cstdio>#include<algorithm>using namespace std;#define keyTree ch[ch[root][1]][0]const int MAXN=200005;struct Splay {    int tot,root;    int ch[MAXN][2],pre[MAXN],size[MAXN];    void rotate(int x,int f) {        int y=pre[x];        ch[y][f^1]=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;        push_up(y);    }    void splay(int x,int goal) {        while(pre[x]!=goal)            if(pre[pre[x]]==goal)                rotate(x,ch[pre[x]][0]==x);            else {                int y=pre[x],z=pre[y],f=ch[z][0]==y;                if(ch[y][f]==x)                    rotate(x,f^1);                else                    rotate(y,f);                rotate(x,f);            }        push_up(x);        if(goal==0)            root=x;    }    void rotate_to(int k,int goal) {        int x=root;        while(size[ch[x][0]]!=k)            if(k<size[ch[x][0]])                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }        splay(x,goal);    }    void NewNode(int &x,int c,int fa) {        x=++tot;        ch[x][0]=ch[x][1]=0;        size[x]=1;        pre[x]=fa;        val[x]=vmax[x]=c;    }    void push_up(int x) {        size[x]=size[ch[x][0]]+1+size[ch[x][1]];        vmax[x]=max(val[x],max(vmax[ch[x][0]],vmax[ch[x][1]]));    }    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(ch[x][0],l,m-1,x);        build(ch[x][1],m+1,r,x);        push_up(x);    }    void init(int n) {        root=tot=0;        ch[0][0]=ch[0][1]=size[0]=0;        vmax[0]=0;        NewNode(root,-1,0);        NewNode(ch[root][1],-1,root);        size[root]=2;        for(int i=1; i<=n; ++i)            scanf("%d",&num[i]);        build(keyTree,1,n,ch[root][1]);        push_up(ch[root][1]);        push_up(root);    }    void update(int p,int v) {        rotate_to(p-1,0);        rotate_to(p+1,root);        val[keyTree]=v;        vmax[keyTree]=max(vmax[keyTree],v);    }    long long query(int l,int r) {        rotate_to(l-1,0);        rotate_to(r+1,root);        return vmax[keyTree];    }    int num[MAXN],val[MAXN],vmax[MAXN];} splay;int main() {    int n,q,a,b;    char op;    while(~scanf("%d%d",&n,&q)) {        splay.init(n);        while(q--) {            scanf(" %c%d%d",&op,&a,&b);            switch(op) {            case 'Q':                printf("%d\n",splay.query(a,b));                break;            case 'U':                splay.update(a,b);                break;            }        }    }}

  POJ3468

  难度一星半;区间增减,区间求和,树状数组、线段树、Splay各一发。

#include<cstdio>#include<cstring>using namespace std;const int MAXN=100005;long long bit1[MAXN],bit2[MAXN];int n;inline int lowbit(int x) {    return x&-x;}void add(int x,int val) {    for(int i=x; i>0; i-=lowbit(i))        bit1[i]+=val;    for(int i=x; i<=n; i+=lowbit(i))        bit2[i]+=x*(long long)val;}long long sum(int x) {    if(!x)        return 0;    long long sum1=0,sum2=0;    for(int i=x; i<=n; i+=lowbit(i))        sum1+=bit1[i];    for(int i=x-1; i>0; i-=lowbit(i))        sum2+=bit2[i];    return sum1*x+sum2;}int main() {    int q,a,b,c;    char op;    while(~scanf("%d%d",&n,&q)) {        memset(bit1,0,sizeof(bit1));        memset(bit2,0,sizeof(bit2));        for(int i=1; i<=n; ++i) {            scanf("%d",&c);            add(i,c);            if(i>1)                add(i-1,-c);        }        while(q--) {            scanf(" %c%d%d",&op,&a,&b);            switch(op) {            case 'Q':                printf("%I64d\n",sum(b)-sum(a-1));                break;            case 'C':                scanf("%d",&c);                add(b,c);                if(a>1)                    add(a-1,-c);                break;            }        }    }}
#include<cstdio>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int MAXN=100005;long long sum[MAXN<<2],col[MAXN<<2];void PushUp(int rt) {    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void PushDown(int rt,int m) {    if(col[rt]) {        col[rt<<1]+=col[rt];        col[rt<<1|1]+=col[rt];        sum[rt<<1]+=col[rt]*(m-(m>>1));        sum[rt<<1|1]+=col[rt]*(m>>1);        col[rt]=0;    }}void build(int l,int r,int rt) {    col[rt]=0;    if(l==r) {        scanf("%I64d",&sum[rt]);        return;    }    int m=l+r>>1;    build(lson);    build(rson);    PushUp(rt);}void update(int L,int R,int val,int l,int r,int rt) {    if(L<=l&&r<=R) {        col[rt]+=val;        sum[rt]+=val*(r-l+1);        return;    }    PushDown(rt,r-l+1);    int m=l+r>>1;    if(L<=m)        update(L,R,val,lson);    if(m<R)        update(L,R,val,rson);    PushUp(rt);}long long query(int L,int R,int l,int r,int rt) {    if(L<=l&&r<=R)        return sum[rt];    PushDown(rt,r-l+1);    int m=l+r>>1;    long long ret=0;    if(L<=m)        ret+=query(L,R,lson);    if(m<R)        ret+=query(L,R,rson);    return ret;}int main() {    int n,q,a,b,c;    char op;    while(~scanf("%d%d",&n,&q)) {        build(1,n,1);        while(q--) {            scanf(" %c%d%d",&op,&a,&b);            switch(op) {            case 'Q':                printf("%I64d\n",query(a,b,1,n,1));                break;            case 'C':                scanf("%d",&c);                update(a,b,c,1,n,1);                break;            }        }    }}
#include<cstdio>using namespace std;#define keyTree ch[ch[root][1]][0]const int MAXN=100005;struct Splay {    int root,tot;    int ch[MAXN][2],pre[MAXN],size[MAXN];    void rotate(int x,int f) {        int y=pre[x];        ch[y][f^1]=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;        push_up(y);    }    void splay(int x,int goal) {        push_down(x);        while(pre[x]!=goal) {            int y=pre[x],z=pre[y];            if(z==goal) {                push_down(y);                push_down(x);                rotate(x,ch[y][0]==x);            } else {                push_down(z);                push_down(y);                push_down(x);                int f=ch[z][0]==y;                if(ch[y][f]==x)                    rotate(x,f^1);                else                    rotate(y,f);                rotate(x,f);            }        }        push_up(x);        if(goal==0)            root=x;    }    void rotate_to(int k,int goal) {        int x=root;        push_down(x);        while(size[ch[x][0]]!=k) {            if(k<size[ch[x][0]])                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }            push_down(x);        }        splay(x,goal);    }    void NewNode(int &x,int c,int fa) {        x=++tot;        ch[x][0]=ch[x][1]=0;        pre[x]=fa;        size[x]=1;        val[x]=sum[x]=c;        add[x]=0;    }    void push_up(int x) {        size[x]=size[ch[x][0]]+1+size[ch[x][1]];        sum[x]=val[x]+sum[ch[x][0]]+sum[ch[x][1]];    }    void push_down(int x) {        if(add[x]) {            val[x]+=add[x];            add[ch[x][0]]+=add[x];            add[ch[x][1]]+=add[x];            sum[ch[x][0]]+=(long long)size[ch[x][0]]*add[x];            sum[ch[x][1]]+=(long long)size[ch[x][1]]*add[x];            add[x]=0;        }    }    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(ch[x][0],l,m-1,x);        build(ch[x][1],m+1,r,x);        push_up(x);    }    void init(int n) {        root=tot=0;        ch[0][0]=ch[0][1]=size[0]=0;        add[0]=sum[0]=0;        NewNode(root,-1,0);        NewNode(ch[root][1],-1,root);        size[root]=2;        for(int i=1; i<=n; ++i)            scanf("%d",&num[i]);        build(keyTree,1,n,ch[root][1]);        push_up(ch[root][1]);        push_up(root);    }    void update(int l,int r,int v) {        rotate_to(l-1,0);        rotate_to(r+1,root);        add[keyTree]+=v;        sum[keyTree]+=(long long)v*size[keyTree];    }    long long query(int l,int r) {        rotate_to(l-1,0);        rotate_to(r+1,root);        return sum[keyTree];    }    int num[MAXN],val[MAXN],add[MAXN];    long long sum[MAXN];} splay;int main() {    int n,q,a,b,c;    char op;    while(~scanf("%d%d",&n,&q)) {        splay.init(n);        while(q--) {            scanf(" %c%d%d",&op,&a,&b);            switch(op) {            case 'Q':                printf("%I64d\n",splay.query(a,b));                break;            case 'C':                scanf("%d",&c);                splay.update(a,b,c);                break;            }        }    }}

  POJ3667

  难度两颗星;区间合并。线段树一发。

#include<cstdio>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int MAXN=50005;int cnt[MAXN<<2],lcnt[MAXN<<2],rcnt[MAXN<<2],mark[MAXN<<2];void push_up(int rt,int len) {    cnt[rt]=max(rcnt[rt<<1]+lcnt[rt<<1|1],max(cnt[rt<<1],cnt[rt<<1|1]));    lcnt[rt]=lcnt[rt<<1];    if(lcnt[rt]==len-(len>>1))        lcnt[rt]+=lcnt[rt<<1|1];    rcnt[rt]=rcnt[rt<<1|1];    if(rcnt[rt]==(len>>1))        rcnt[rt]+=rcnt[rt<<1];}void push_down(int rt,int len) {    if(~mark[rt]) {        cnt[rt<<1]=lcnt[rt<<1]=rcnt[rt<<1]=mark[rt]?0:len-(len>>1);        cnt[rt<<1|1]=lcnt[rt<<1|1]=rcnt[rt<<1|1]=mark[rt]?0:(len>>1);        mark[rt<<1]=mark[rt<<1|1]=mark[rt];        mark[rt]=-1;    }}void build(int l,int r,int rt) {    mark[rt]=-1;    cnt[rt]=lcnt[rt]=rcnt[rt]=r-l+1;    if(l==r)        return;    int m=l+r>>1;    build(lson);    build(rson);}void update(int L,int R,int col,int l,int r,int rt) {    if(L<=l&&r<=R) {        cnt[rt]=lcnt[rt]=rcnt[rt]=col?0:r-l+1;        mark[rt]=col;        return;    }    push_down(rt,r-l+1);    int m=l+r>>1;    if(L<=m)        update(L,R,col,lson);    if(m<R)        update(L,R,col,rson);    push_up(rt,r-l+1);}int query(int len,int l,int r,int rt) {    if(cnt[rt]<len)        return 0;    if(l==r)        return l;    push_down(rt,r-l+1);    int m=l+r>>1;    if(cnt[rt<<1]>=len)        return query(len,lson);    else if(rcnt[rt<<1]+lcnt[rt<<1|1]>=len)        return m+1-rcnt[rt<<1];    else if(cnt[rt<<1|1]>=len)        return query(len,rson);}int main() {    int n,m,op,x,d,ans;    while(~scanf("%d%d",&n,&m)) {        build(1,n,1);        while(m--) {            scanf("%d",&op);            switch(op) {            case 1:                scanf("%d",&d);                ans=query(d,1,n,1);                printf("%d\n",ans);                if(ans)                    update(ans,ans+d-1,1,1,n,1);                break;            case 2:                scanf("%d%d",&x,&d);                update(x,x+d-1,0,1,n,1);                break;            }        }    }}

  HDU2871

  难度两星半;区间合并。两种姿势线段树各一发。

#include<cstdio>#include<algorithm>#include<vector>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int MAXN=50005;int cnt[MAXN<<2],lcnt[MAXN<<2],rcnt[MAXN<<2],mark[MAXN<<2];void push_up(int rt,int len) {    cnt[rt]=max(rcnt[rt<<1]+lcnt[rt<<1|1],max(cnt[rt<<1],cnt[rt<<1|1]));    lcnt[rt]=lcnt[rt<<1];    if(lcnt[rt]==len-(len>>1))        lcnt[rt]+=lcnt[rt<<1|1];    rcnt[rt]=rcnt[rt<<1|1];    if(rcnt[rt]==(len>>1))        rcnt[rt]+=rcnt[rt<<1];}void push_down(int rt,int len) {    if(~mark[rt]) {        cnt[rt<<1]=lcnt[rt<<1]=rcnt[rt<<1]=mark[rt]?0:len-(len>>1);        cnt[rt<<1|1]=lcnt[rt<<1|1]=rcnt[rt<<1|1]=mark[rt]?0:(len>>1);        mark[rt<<1]=mark[rt<<1|1]=mark[rt];        mark[rt]=-1;    }}void build(int l,int r,int rt) {    mark[rt]=-1;    cnt[rt]=lcnt[rt]=rcnt[rt]=r-l+1;    if(l==r)        return;    int m=l+r>>1;    build(lson);    build(rson);}void update(int L,int R,int col,int l,int r,int rt) {    if(L<=l&&r<=R) {        cnt[rt]=lcnt[rt]=rcnt[rt]=col?0:r-l+1;        mark[rt]=col;        return;    }    push_down(rt,r-l+1);    int m=l+r>>1;    if(L<=m)        update(L,R,col,lson);    if(m<R)        update(L,R,col,rson);    push_up(rt,r-l+1);}int query(int len,int l,int r,int rt) {    if(l==r)        return l;    push_down(rt,r-l+1);    int m=l+r>>1;    if(cnt[rt<<1]>=len)        return query(len,lson);    else if(rcnt[rt<<1]+lcnt[rt<<1|1]>=len)        return m+1-rcnt[rt<<1];    else if(cnt[rt<<1|1]>=len)        return query(len,rson);}vector<pair<int,int> > block;vector<pair<int,int> >::iterator it;int main() {    int n,m,x,a;    char op[8];    pair<int,int> tmp;    while(~scanf("%d%d",&n,&m)) {        build(1,n,1);        block.clear();        while(m--) {            scanf("%s",op);            switch(op[0]) {            case 'R':                update(1,n,0,1,n,1);                block.clear();                puts("Reset Now");                break;            case 'N':                scanf("%d",&x);                if(cnt[1]>=x) {                    a=query(x,1,n,1);                    update(a,a+x-1,1,1,n,1);                    tmp=make_pair(a,a+x-1);                    it=upper_bound(block.begin(),block.end(),tmp);                    block.insert(it,tmp);                    printf("New at %d\n",a);                } else                    puts("Reject New");                break;            case 'F':                scanf("%d",&x);                it=upper_bound(block.begin(),block.end(),make_pair(x,n+1));                if(it==block.begin())                    puts("Reject Free");                else {                    --it;                    if(it->second<x)                        puts("Reject Free");                    else {                        update(it->first,it->second,0,1,n,1);                        printf("Free from %d to %d\n",it->first,it->second);                        block.erase(it);                    }                }                break;            case 'G':                scanf("%d",&x);                if(x<=block.size())                    printf("Get at %d\n",block[x-1].first);                else                    puts("Reject Get");                break;            }        }        putchar('\n');    }}
#include<cstdio>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int MAXN=50005;int cnt[MAXN<<2],lcnt[MAXN<<2],rcnt[MAXN<<2],mark[MAXN<<2],start[MAXN<<2],end[MAXN<<2],num[MAXN<<2];bool cover[MAXN<<2];void push_up(int rt,int len) {    cnt[rt]=max(rcnt[rt<<1]+lcnt[rt<<1|1],max(cnt[rt<<1],cnt[rt<<1|1]));    lcnt[rt]=lcnt[rt<<1];    if(lcnt[rt]==len-(len>>1))        lcnt[rt]+=lcnt[rt<<1|1];    rcnt[rt]=rcnt[rt<<1|1];    if(rcnt[rt]==(len>>1))        rcnt[rt]+=rcnt[rt<<1];}void push_down(int rt,int len) {    if(~mark[rt]) {        cnt[rt<<1]=lcnt[rt<<1]=rcnt[rt<<1]=mark[rt]?0:len-(len>>1);        cnt[rt<<1|1]=lcnt[rt<<1|1]=rcnt[rt<<1|1]=mark[rt]?0:(len>>1);        start[rt<<1]=start[rt<<1|1]=start[rt];        end[rt<<1]=end[rt<<1|1]=end[rt];        mark[rt<<1]=mark[rt<<1|1]=mark[rt];        mark[rt]=-1;    }}void update(int L,int R,int col,int l,int r,int rt) {    if(L<=l&&r<=R) {        cnt[rt]=lcnt[rt]=rcnt[rt]=col?0:r-l+1;        mark[rt]=col;        if(col) {            start[rt]=L;            end[rt]=R;        } else            start[rt]=end[rt]=-1;        return;    }    push_down(rt,r-l+1);    int m=l+r>>1;    if(L<=m)        update(L,R,col,lson);    if(m<R)        update(L,R,col,rson);    push_up(rt,r-l+1);}int New(int len,int l,int r,int rt) {    if(l==r)        return l;    push_down(rt,r-l+1);    int m=l+r>>1;    if(cnt[rt<<1]>=len)        return New(len,lson);    else if(rcnt[rt<<1]+lcnt[rt<<1|1]>=len)        return m+1-rcnt[rt<<1];    else if(cnt[rt<<1|1]>=len)        return New(len,rson);}int Free(int p,int l,int r,int rt) {    if(l==r)        return rt;    push_down(rt,r-l+1);    int m=l+r>>1;    if(p<=m)        return Free(p,lson);    else        return Free(p,rson);}void count_up(int rt) {    num[rt]=num[rt<<1]+num[rt<<1|1];}void count_down(int rt) {    if(cover[rt]) {        num[rt<<1]=num[rt<<1|1]=0;        cover[rt<<1]=cover[rt<<1|1]=cover[rt];        cover[rt]=false;    }}void count(int p,int val,int l,int r,int rt) {    if(l==r) {        num[rt]=val;        return;    }    count_down(rt);    int m=l+r>>1;    if(p<=m)        count(p,val,lson);    else        count(p,val,rson);    count_up(rt);}int Get(int k,int l,int r,int rt) {    if(l==r)        return l;    int m=l+r>>1;    count_down(rt);    if(num[rt<<1]>=k)        return Get(k,lson);    else        return Get(k-num[rt<<1],rson);}int main() {    int n,m,x,a;    char op[8];    while(~scanf("%d%d",&n,&m)) {        update(1,n,0,1,n,1);        cover[1]=true;        num[1]=0;        while(m--) {            scanf("%s",op);            switch(op[0]) {            case 'R':                puts("Reset Now");                update(1,n,0,1,n,1);                cover[1]=true;                num[1]=0;                break;            case 'N':                scanf("%d",&x);                if(cnt[1]>=x) {                    a=New(x,1,n,1);                    printf("New at %d\n",a);                    count(a,1,1,n,1);                    update(a,a+x-1,1,1,n,1);                } else                    puts("Reject New");                break;            case 'F':                scanf("%d",&x);                a=Free(x,1,n,1);                if(~start[a]) {                    printf("Free from %d to %d\n",start[a],end[a]);                    count(start[a],0,1,n,1);                    update(start[a],end[a],0,1,n,1);                } else                    puts("Reject Free");                break;            case 'G':                scanf("%d",&x);                if(num[1]>=x)                    printf("Get at %d\n",Get(x,1,n,1));                else                    puts("Reject Get");                break;            }        }        putchar('\n');    }}

  HDU4902

  难度两星半;区间带限制覆盖,区间最值,多重lazy标记。线段树一发。

#include<cstdio>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int N=100005;int cover[N<<2],vmax[N<<2];bool same[N<<2];void push_up(int rt) {    vmax[rt]=max(vmax[rt<<1],vmax[rt<<1|1]);    same[rt]=same[rt<<1]&&same[rt<<1|1]&&vmax[rt<<1]==vmax[rt<<1|1];}void push_down(int rt) {    if(cover[rt]) {        vmax[rt<<1]=vmax[rt<<1|1]=cover[rt<<1]=cover[rt<<1|1]=cover[rt];        cover[rt]=0;    }    if(same[rt])        same[rt<<1]=same[rt<<1|1]=true;}void build(int l,int r,int rt) {    cover[rt]=0;    same[rt]=false;    if(l==r) {        scanf("%d",&vmax[rt]);        return;    }    int m=l+r>>1;    build(lson);    build(rson);    push_up(rt);}void upcover(int L,int R,int v,int l,int r,int rt) {    if(L<=l&&r<=R) {        vmax[rt]=cover[rt]=v;        same[rt]=true;        return;    }    push_down(rt);    int m=l+r>>1;    if(L<=m)        upcover(L,R,v,lson);    if(m<R)        upcover(L,R,v,rson);    push_up(rt);}void upgcd(int L,int R,int v,int l,int r,int rt) {    if(vmax[rt]<=v)        return;    if(l==r||(L<=l&&r<=R&&same[rt])) {        cover[rt]=vmax[rt]=__gcd(vmax[rt],v);        same[rt]=true;        return;    }    push_down(rt);    int m=l+r>>1;    if(L<=m)        upgcd(L,R,v,lson);    if(m<R)        upgcd(L,R,v,rson);    push_up(rt);}int query(int p,int l,int r,int rt) {    if(l==r)        return vmax[rt];    push_down(rt);    int m=l+r>>1;    if(p<=m)        return query(p,lson);    else        return query(p,rson);}int main() {    int T,n,q,a,t,l,r,x;    scanf("%d",&T);    while(T--) {        scanf("%d",&n);        build(1,n,1);        scanf("%d",&q);        while(q--) {            scanf("%d%d%d%d",&t,&l,&r,&x);            switch(t) {            case 1:                upcover(l,r,x,1,n,1);                break;            case 2:                upgcd(l,r,x,1,n,1);                break;            }        }        for(int i=1; i<=n; ++i)            printf("%d ",query(i,1,n,1));        putchar('\n');    }}

  HDU4819

  难度三颗星;二维平面单点修改,区间最值。四分树、二维线段树各一发。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define tl xl,xm,yl,ym,rt<<2#define tr xl,xm,ym+1,yr,(rt<<2)+1#define dl xm+1,xr,yl,ym,(rt<<2)+2#define dr xm+1,xr,ym+1,yr,(rt<<2)+3const int MAXN=805;const int INF=0x3f3f3f3f;int vmax[MAXN<<12],vmin[MAXN<<12];void push_up(int rt) {    vmax[rt]=max(max(vmax[rt<<2],vmax[(rt<<2)+1]),max(vmax[(rt<<2)+2],vmax[(rt<<2)+3]));    vmin[rt]=min(min(vmin[rt<<2],vmin[(rt<<2)+1]),min(vmin[(rt<<2)+2],vmin[(rt<<2)+3]));}void update(int x,int y,int v,int xl,int xr,int yl,int yr,int rt) {    if(xl==xr&&yl==yr) {        vmax[rt]=vmin[rt]=v;        return;    }    int xm=xl+xr>>1,ym=yl+yr>>1;    if(x<=xm) {        if(y<=ym)            update(x,y,v,tl);        else            update(x,y,v,tr);    } else {        if(y<=ym)            update(x,y,v,dl);        else            update(x,y,v,dr);    }    push_up(rt);}pair<int,int> query(int xL,int xR,int yL,int yR,int xl,int xr,int yl,int yr,int rt) {    if(xL<=xl&&xr<=xR&&yL<=yl&&yr<=yR)        return make_pair(vmax[rt],vmin[rt]);    int xm=xl+xr>>1,ym=yl+yr>>1,retmax=0,retmin=INF;    pair<int,int> tmp;    if(xL<=xm&&yL<=ym) {        tmp=query(xL,xR,yL,yR,tl);        retmax=max(retmax,tmp.first);        retmin=min(retmin,tmp.second);    }    if(xL<=xm&&yR>ym) {        tmp=query(xL,xR,yL,yR,tr);        retmax=max(retmax,tmp.first);        retmin=min(retmin,tmp.second);    }    if(xR>xm&&yL<=ym) {        tmp=query(xL,xR,yL,yR,dl);        retmax=max(retmax,tmp.first);        retmin=min(retmin,tmp.second);    }    if(xR>xm&&yR>ym) {        tmp=query(xL,xR,yL,yR,dr);        retmax=max(retmax,tmp.first);        retmin=min(retmin,tmp.second);    }    return make_pair(retmax,retmin);}int main() {    int t,n,v,q,x,y,l;    scanf("%d",&t);    for(int cas=1; cas<=t; ++cas) {        scanf("%d",&n);        memset(vmax,0,sizeof(vmax));        memset(vmin,0x3f,sizeof(vmin));        for(int i=1; i<=n; ++i)            for(int j=1; j<=n; ++j) {                scanf("%d",&v);                update(i,j,v,1,n,1,n,1);            }        scanf("%d",&q);        printf("Case #%d:\n",cas);        while(q--) {            scanf("%d%d%d",&x,&y,&l);            pair<int,int> ans=query(max(x-l/2,1),min(x+l/2,n),max(y-l/2,1),min(y+l/2,n),1,n,1,n,1);            printf("%d\n",(ans.first+ans.second)/2);            update(x,y,(ans.first+ans.second)/2,1,n,1,n,1);        }    }}
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int MAXN=805;const int INF=0x3f3f3f3f;int vmax[MAXN<<2][MAXN<<2],vmin[MAXN<<2][MAXN<<2],n;void push_up(int x,int rt) {    vmax[x][rt]=max(vmax[x][rt<<1],vmax[x][rt<<1|1]);    vmin[x][rt]=min(vmin[x][rt<<1],vmin[x][rt<<1|1]);}void push_up1(int x,int rt) {    vmax[x][rt]=max(vmax[x<<1][rt],vmax[x<<1|1][rt]);    vmin[x][rt]=min(vmin[x<<1][rt],vmin[x<<1|1][rt]);}void build(int x,int l,int r,int rt) {    vmax[x][rt]=0;    vmin[x][rt]=INF;    if(l==r)        return;    int m=l+r>>1;    build(x,lson);    build(x,rson);}void build(int l,int r,int rt) {    if(l==r) {        build(rt,1,n,1);        return;    }    int m=l+r>>1;    build(lson);    build(rson);}void update2(int x,int p,int v,int l,int r,int rt) {    if(l==r) {        vmax[x][rt]=vmin[x][rt]=v;        return;    }    int m=l+r>>1;    if(p<=m)        update2(x,p,v,lson);    else        update2(x,p,v,rson);    push_up(x,rt);}void update1(int x,int p,int v,int l,int r,int rt) {    if(l==r) {        push_up1(x,rt);        return;    }    int m=l+r>>1;    if(p<=m)        update1(x,p,v,lson);    else        update1(x,p,v,rson);    push_up(x,rt);}void update(int p,int q,int v,int l,int r,int rt) {    if(l==r) {        update2(rt,q,v,1,n,1);        return;    }    int m=l+r>>1;    if(p<=m)        update(p,q,v,lson);    else        update(p,q,v,rson);    update1(rt,q,v,1,n,1);}pair<int,int> query(int x,int L,int R,int l,int r,int rt) {    if(L<=l&&r<=R)        return make_pair(vmax[x][rt],vmin[x][rt]);    int m=l+r>>1,retmax=0,retmin=INF;    pair<int,int> tmp;    if(L<=m) {        tmp=query(x,L,R,lson);        retmax=max(retmax,tmp.first);        retmin=min(retmin,tmp.second);    }    if(m<R) {        tmp=query(x,L,R,rson);        retmax=max(retmax,tmp.first);        retmin=min(retmin,tmp.second);    }    return make_pair(retmax,retmin);}pair<int,int> query(int xL,int xR,int yL,int yR,int l,int r,int rt) {    if(xL<=l&&r<=xR)        return query(rt,yL,yR,1,n,1);    int m=l+r>>1,retmax=0,retmin=INF;    pair<int,int> tmp;    if(xL<=m) {        tmp=query(xL,xR,yL,yR,lson);        retmax=max(retmax,tmp.first);        retmin=min(retmin,tmp.second);    }    if(m<xR) {        tmp=query(xL,xR,yL,yR,rson);        retmax=max(retmax,tmp.first);        retmin=min(retmin,tmp.second);    }    return make_pair(retmax,retmin);}int main() {    int t,v,q,x,y,l;    scanf("%d",&t);    for(int cas=1; cas<=t; ++cas) {        scanf("%d",&n);        build(1,n,1);        for(int i=1; i<=n; ++i)            for(int j=1; j<=n; ++j) {                scanf("%d",&v);                update(i,j,v,1,n,1);            }        scanf("%d",&q);        printf("Case #%d:\n",cas);        while(q--) {            scanf("%d%d%d",&x,&y,&l);            pair<int,int> ans=query(max(x-l/2,1),min(x+l/2,n),max(y-l/2,1),min(y+l/2,n),1,n,1);            printf("%d\n",(ans.first+ans.second)/2);            update(x,y,(ans.first+ans.second)/2,1,n,1);        }    }}

  POJ3321

  难度两颗星;树上单点修改,子树求和。树上dfs序+树状数组、树上dfs序+线段树各一发。

#include<cstdio>#include<cstring>using namespace std;const int MAXN=1000005;const int MAXM=MAXN;struct graph {    int head[MAXN];    int to[MAXM],next[MAXM];    int tot;    void init() {        tot=0;        memset(head,0xff,sizeof(head));    }    void add(int u,int v) {        to[tot]=v;        next[tot]=head[u];        head[u]=tot++;    }} g;int bit[MAXN],n;inline int lowbit(int x) {    return x&-x;}void add(int x,int val) {    for(int i=x; i<=n; i+=lowbit(i))        bit[i]+=val;}int sum(int x) {    int ret=0;    for(int i=x; i>0; i-=lowbit(i))        ret+=bit[i];    return ret;}int low[MAXN],high[MAXN],cnt;void dfs(int u) {    low[u]=++cnt;    for(int i=g.head[u]; ~i; i=g.next[i])        dfs(g.to[i]);    high[u]=cnt;}int main() {    int u,v,m,x;    char op;    while(~scanf("%d",&n)) {        g.init();        for(int i=1; i<n; ++i) {            scanf("%d%d",&u,&v);            g.add(u,v);        }        cnt=0;        dfs(1);        memset(bit,0,sizeof(bit));        for(int i=1; i<=n; ++i)            add(i,1);        scanf("%d",&m);        while(m--) {            scanf(" %c%d",&op,&x);            switch(op) {            case 'C':                add(low[x],!(sum(low[x])-sum(low[x]-1))?1:-1);                break;            case 'Q':                printf("%d\n",sum(high[x])-sum(low[x]-1));                break;            }        }    }}
#include<cstdio>#include<cstring>using namespace std;const int MAXN=1000005;const int MAXM=MAXN;struct graph {    int head[MAXN];    int to[MAXM],next[MAXM];    int tot;    void init() {        tot=0;        memset(head,0xff,sizeof(head));    }    void add(int u,int v) {        to[tot]=v;        next[tot]=head[u];        head[u]=tot++;    }} g;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int sum[MAXN<<2];void push_up(int rt) {    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt) {    if(l==r) {        sum[rt]=1;        return;    }    int m=l+r>>1;    build(lson);    build(rson);    push_up(rt);}void update(int p,int val,int l,int r,int rt) {    if(l==r) {        sum[rt]+=val;        return;    }    int m=l+r>>1;    if(p<=m)        update(p,val,lson);    else        update(p,val,rson);    push_up(rt);}int query(int L,int R,int l,int r,int rt) {    if(L<=l&&r<=R)        return sum[rt];    int m=l+r>>1,ret=0;    if(L<=m)        ret+=query(L,R,lson);    if(m<R)        ret+=query(L,R,rson);    return ret;}int low[MAXN],high[MAXN],cnt;void dfs(int u) {    low[u]=++cnt;    for(int i=g.head[u]; ~i; i=g.next[i])        dfs(g.to[i]);    high[u]=cnt;}int main() {    int n,u,v,m,x;    char op;    while(~scanf("%d",&n)) {        g.init();        for(int i=1; i<n; ++i) {            scanf("%d%d",&u,&v);            g.add(u,v);        }        cnt=0;        dfs(1);        build(1,n,1);        scanf("%d",&m);        while(m--) {            scanf(" %c%d",&op,&x);            switch(op) {            case 'C':                update(low[x],!query(low[x],low[x],1,n,1)?1:-1,1,n,1);                break;            case 'Q':                printf("%d\n",query(low[x],high[x],1,n,1));                break;            }        }    }}

  HDU3887

  难度两星半;树上单点修改,子树带限制求和。树上dfs序+树状数组、树上dfs序+线段树各一发。

#include<cstdio>#include<cstdlib>#include<cstring>using namespace std;const int MAXN=100005;const int MAXM=MAXN<<1;struct graph {    int head[MAXN];    int to[MAXM],next[MAXM];    int tot;    void init() {        tot=0;        memset(head,0xff,sizeof(head));    }    void add(int u,int v) {        to[tot]=v;        next[tot]=head[u];        head[u]=tot++;    }} g;int bit[MAXN],n;inline int lowbit(int x) {    return x&-x;}void add(int x,int val) {    for(int i=x; i<=n; i+=lowbit(i))        bit[i]+=val;}int sum(int x) {    int ret=0;    for(int i=x; i>0; i-=lowbit(i))        ret+=bit[i];    return ret;}int ans[MAXN];void dfs(int u,int pre) {    add(u,1);    ans[u]=sum(u);    for(int i=g.head[u]; ~i; i=g.next[i]) {        int v=g.to[i];        if(v!=pre)            dfs(v,u);    }    ans[u]=sum(u)-ans[u];}int main() {    int __size__=16<<20;    char *__p__=(char*)malloc(__size__)+__size__;    __asm__("movl %0, %%esp\n"::"r"(__p__));    int p,u,v;    while(~scanf("%d%d",&n,&p)&&(n||p)) {        g.init();        for(int i=1; i<n; ++i) {            scanf("%d%d",&u,&v);            g.add(u,v);            g.add(v,u);        }        memset(bit,0,sizeof(bit));        dfs(p,-1);        for(int i=1; i<=n; ++i) {            printf("%d",ans[i]);            putchar(i<n?' ':'\n');        }    }}
#include<cstdio>#include<cstdlib>#include<cstring>using namespace std;const int MAXN=100005;const int MAXM=MAXN<<1;struct graph {    int head[MAXN];    int to[MAXM],next[MAXM];    int tot;    void init() {        tot=0;        memset(head,0xff,sizeof(head));    }    void add(int u,int v) {        to[tot]=v;        next[tot]=head[u];        head[u]=tot++;    }} g;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int sum[MAXN<<2];void build(int l,int r,int rt) {    sum[rt]=0;    if(l==r)        return;    int m=l+r>>1;    build(lson);    build(rson);}void update(int p,int val,int l,int r,int rt) {    if(l==r) {        sum[rt]+=val;        return;    }    int m=l+r>>1;    if(p<=m)        update(p,val,lson);    else        update(p,val,rson);    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}int query(int L,int R,int l,int r,int rt) {    if(L<=l&&r<=R)        return sum[rt];    int m=l+r>>1,ret=0;    if(L<=m)        ret+=query(L,R,lson);    if(m<R)        ret+=query(L,R,rson);    return ret;}int ans[MAXN],n;void dfs(int u,int pre) {    update(u,1,1,n,1);    ans[u]=query(1,u,1,n,1);    for(int i=g.head[u]; ~i; i=g.next[i]) {        int v=g.to[i];        if(v!=pre)            dfs(v,u);    }    ans[u]=query(1,u,1,n,1)-ans[u];}int main() {    int __size__=16<<20;    char *__p__=(char*)malloc(__size__)+__size__;    __asm__("movl %0, %%esp\n"::"r"(__p__));    int p,u,v;    while(~scanf("%d%d",&n,&p)&&(n||p)) {        g.init();        for(int i=1; i<n; ++i) {            scanf("%d%d",&u,&v);            g.add(u,v);            g.add(v,u);        }        build(1,n,1);        dfs(p,-1);        for(int i=1; i<=n; ++i) {            printf("%d",ans[i]);            putchar(i<n?' ':'\n');        }    }}

  HDU3966

  难度三颗星;树上路径修改,单点查询。树上dfs序+LCA+树状数组、树链剖分+树状数组、树链剖分+线段树各一发。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=50005;const int MAXM=MAXN<<1;struct graph {    int head[MAXN];    int to[MAXM],next[MAXM];    int tot;    void init() {        tot=0;        memset(head,0xff,sizeof(head));    }    void add(int u,int v) {        to[tot]=v;        next[tot]=head[u];        head[u]=tot++;    }} g;const int maxd=18;int low[MAXN],high[MAXN],cnt;int d[MAXN],f[MAXN][maxd];void dfs(int u,int fa) {    low[u]=++cnt;    f[u][0]=fa;    d[u]=d[fa]+1;    for(int i=1; i<maxd; ++i)        f[u][i]=f[f[u][i-1]][i-1];    for(int i=g.head[u]; ~i; i=g.next[i]) {        int v=g.to[i];        if(v!=fa)            dfs(v,u);    }    high[u]=++cnt;}int lca(int u,int v) {    if(d[u]<d[v])        swap(u,v);    int k=d[u]-d[v];    for(int i=0; i<maxd; ++i)        if((1<<i)&k)            u=f[u][i];    if(u==v)        return u;    for(int i=maxd-1; i>=0; --i)        if(f[u][i]!=f[v][i]) {            u=f[u][i];            v=f[v][i];        }    return f[u][0];}int bit[MAXN<<1];inline int lowbit(int x) {    return x&-x;}void add(int x,int val) {    for(int i=x; i>0; i-=lowbit(i))        bit[i]+=val;}int get(int x) {    int ret=0;    for(int i=x; i<=cnt; i+=lowbit(i))        ret+=bit[i];    return ret;}void modify(int x,int y,int d) {    add(low[x],d);    add(low[y],d);    int fa=lca(x,y);    add(low[fa]-1,-d);    add(low[fa],-d);}int a[MAXN];int main() {    int n,m,p,u,v,c,k;    char op;    while(~scanf("%d%d%d",&n,&m,&p)) {        for(int i=1; i<=n; ++i)            scanf("%d",&a[i]);        g.init();        while(m--) {            scanf("%d%d",&u,&v);            g.add(u,v);            g.add(v,u);        }        cnt=0;        dfs(1,-1);        memset(bit,0,sizeof(bit));        while(p--) {            scanf(" %c",&op);            switch(op) {            case 'I':                scanf("%d%d%d",&u,&v,&k);                modify(u,v,k);                break;            case 'D':                scanf("%d%d%d",&u,&v,&k);                modify(u,v,-k);                break;            case 'Q':                scanf("%d",&c);                printf("%d\n",a[c]+get(low[c])-get(high[c]));                break;            }        }    }}
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=50005;const int MAXM=MAXN<<1;struct graph {    int head[MAXN];    int to[MAXM],next[MAXM];    int tot;    void init() {        tot=0;        memset(head,0xff,sizeof(head));    }    void add(int u,int v) {        to[tot]=v;        next[tot]=head[u];        head[u]=tot++;    }} g;int top[MAXN],len[MAXN];int belong[MAXN],idx[MAXN];int dep[MAXN],fa[MAXN],size[MAXN];int que[MAXN];bool vis[MAXN];int n,cnt;void split() {    memset(dep,0xff,sizeof(dep));    int l=0,r=0;    que[++r]=1;    dep[1]=0;    fa[1]=-1;    while(l<r) {        int u=que[++l];        vis[u]=false;        for(int i=g.head[u]; ~i; i=g.next[i]) {            int v=g.to[i];            if(!~dep[v]) {                que[++r]=v;                dep[v]=dep[u]+1;                fa[v]=u;            }        }    }    cnt=0;    for(int i=n; i>0; --i) {        int u=que[i],p=-1;        size[u]=1;        for(int j=g.head[u]; ~j; j=g.next[j]) {            int v=g.to[j];            if(vis[v]) {                size[u]+=size[v];                if(!~p||size[v]>size[p])                    p=v;            }        }        if(!~p) {            idx[u]=len[++cnt]=1;            belong[u]=cnt;            top[cnt]=u;        } else {            belong[u]=belong[p];            idx[u]=++len[belong[u]];            top[belong[u]]=u;        }        vis[u]=true;    }}int fi[MAXN],cid[MAXN],rank[MAXN];void getcid() {    fi[1]=1;    for(int i=2; i<=cnt; ++i)        fi[i]=fi[i-1]+len[i-1];    for(int i=1; i<=n; ++i) {        cid[i]=fi[belong[i]]+len[belong[i]]-idx[i];        rank[cid[i]]=i;    }}int bit[MAXN];inline int lowbit(int x) {    return x&-x;}void add(int x,int val) {    for(int i=x; i>0; i-=lowbit(i))        bit[i]+=val;}int sum(int x) {    int ret=0;    for(int i=x; i<=n; i+=lowbit(i))        ret+=bit[i];    return ret;}void modify(int x,int y,int d) {    while(belong[x]!=belong[y]) {        if(dep[top[belong[x]]]<dep[top[belong[y]]])            swap(x,y);        add(cid[top[belong[x]]]-1,-d);        add(cid[x],d);        x=fa[top[belong[x]]];    }    if(dep[x]>dep[y])        swap(x,y);    add(cid[x]-1,-d);    add(cid[y],d);}int a[MAXN];int main() {    int m,p,u,v,c,k;    char op;    while(~scanf("%d%d%d",&n,&m,&p)) {        for(int i=1; i<=n; ++i)            scanf("%d",&a[i]);        g.init();        while(m--) {            scanf("%d%d",&u,&v);            g.add(u,v);            g.add(v,u);        }        split();        getcid();        memset(bit,0,sizeof(bit));        while(p--) {            scanf(" %c",&op);            switch(op) {            case 'I':                scanf("%d%d%d",&u,&v,&k);                modify(u,v,k);                break;            case 'D':                scanf("%d%d%d",&u,&v,&k);                modify(u,v,-k);                break;            case 'Q':                scanf("%d",&c);                printf("%d\n",a[c]+sum(cid[c]));                break;            }        }    }}
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=50005;const int MAXM=MAXN<<1;struct graph {    int head[MAXN];    int to[MAXM],next[MAXM];    int tot;    void init() {        tot=0;        memset(head,0xff,sizeof(head));    }    void add(int u,int v) {        to[tot]=v;        next[tot]=head[u];        head[u]=tot++;    }} g;int top[MAXN],len[MAXN];int belong[MAXN],idx[MAXN];int dep[MAXN],fa[MAXN],size[MAXN];int que[MAXN];bool vis[MAXN];int n,cnt;void split() {    memset(dep,0xff,sizeof(dep));    int l=0,r=0;    que[++r]=1;    dep[1]=0;    fa[1]=-1;    while(l<r) {        int u=que[++l];        vis[u]=false;        for(int i=g.head[u]; ~i; i=g.next[i]) {            int v=g.to[i];            if(!~dep[v]) {                que[++r]=v;                dep[v]=dep[u]+1;                fa[v]=u;            }        }    }    cnt=0;    for(int i=n; i>0; --i) {        int u=que[i],p=-1;        size[u]=1;        for(int j=g.head[u]; ~j; j=g.next[j]) {            int v=g.to[j];            if(vis[v]) {                size[u]+=size[v];                if(!~p||size[v]>size[p])                    p=v;            }        }        if(!~p) {            idx[u]=len[++cnt]=1;            belong[u]=cnt;            top[cnt]=u;        } else {            belong[u]=belong[p];            idx[u]=++len[belong[u]];            top[belong[u]]=u;        }        vis[u]=true;    }}int a[MAXN],fi[MAXN],cid[MAXN],rank[MAXN];void getcid() {    fi[1]=1;    for(int i=2; i<=cnt; ++i)        fi[i]=fi[i-1]+len[i-1];    for(int i=1; i<=n; ++i) {        cid[i]=fi[belong[i]]+len[belong[i]]-idx[i];        rank[cid[i]]=i;    }}#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int sum[MAXN<<2],col[MAXN<<2];void push_up(int rt) {    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void push_down(int rt,int len) {    if(col[rt]) {        col[rt<<1]+=col[rt];        col[rt<<1|1]+=col[rt];        sum[rt<<1]+=col[rt]*(len-(len>>1));        sum[rt<<1|1]+=col[rt]*(len>>1);        col[rt]=0;    }}void build(int l,int r,int rt) {    col[rt]=0;    if(l==r) {        sum[rt]=a[rank[l]];        return;    }    int m=l+r>>1;    build(lson);    build(rson);    push_up(rt);}void update(int L,int R,int val,int l,int r,int rt) {    if(L<=l&&r<=R) {        col[rt]+=val;        sum[rt]+=val*(r-l+1);        return;    }    push_down(rt,r-l+1);    int m=l+r>>1;    if(L<=m)        update(L,R,val,lson);    if(m<R)        update(L,R,val,rson);    push_up(rt);}int query(int p,int l,int r,int rt) {    if(l==r)        return sum[rt];    push_down(rt,r-l+1);    int m=l+r>>1;    if(p<=m)        return query(p,lson);    else        return query(p,rson);}void modify(int x,int y,int d) {    while(belong[x]!=belong[y]) {        if(dep[top[belong[x]]]<dep[top[belong[y]]])            swap(x,y);        update(cid[top[belong[x]]],cid[x],d,1,n,1);        x=fa[top[belong[x]]];    }    if(dep[x]>dep[y])        swap(x,y);    update(cid[x],cid[y],d,1,n,1);}int main() {    int m,p,u,v,c,k;    char op;    while(~scanf("%d%d%d",&n,&m,&p)) {        for(int i=1; i<=n; ++i)            scanf("%d",&a[i]);        g.init();        while(m--) {            scanf("%d%d",&u,&v);            g.add(u,v);            g.add(v,u);        }        split();        getcid();        build(1,n,1);        while(p--) {            scanf(" %c",&op);            switch(op) {            case 'I':                scanf("%d%d%d",&u,&v,&k);                modify(u,v,k);                break;            case 'D':                scanf("%d%d%d",&u,&v,&k);                modify(u,v,-k);                break;            case 'Q':                scanf("%d",&c);                printf("%d\n",query(cid[c],1,n,1));                break;            }        }    }}

  POJ3481

  难度一颗星;平衡树插入、删除。Treap、Size Balanced Tree、Skip List各一发。

#include<cstdio>#include<cstdlib>using namespace std;const int MAXN=1000005;const int INF=0x3f3f3f3f;struct Treap {    int tot,root;    int ch[MAXN][2],key[MAXN],pt[MAXN],size[MAXN],val[MAXN];    Treap() {        tot=1;        root=0;        pt[0]=INF;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    bool insert(int &x,int k,int v) {        if(!x) {            x=tot++;            ch[x][0]=ch[x][1]=0;            key[x]=k;            val[x]=v;            pt[x]=rand();            size[x]=1;            return true;        }        if(key[x]==k)            return false;        int t=key[x]<k;        if(!insert(ch[x][t],k,v))            return false;        ++size[x];        if(pt[ch[x][t]]<pt[x])            rotate(x,t);        return true;    }    bool erase(int &x,int k) {        if(!x)            return false;        if(key[x]!=k) {            if(!erase(ch[x][key[x]<k],k))                return false;            --size[x];        } else if(!ch[x][0]&&!ch[x][1])            x=0;        else if(!ch[x][0])            x=ch[x][1];        else if(!ch[x][1])            x=ch[x][0];        else {            rotate(x,pt[ch[x][0]]>pt[ch[x][1]]);            if(!erase(ch[x][key[x]<k],k))                return false;            --size[x];        }        return true;    }    void insert(int k,int v) {        insert(root,k,v);    }    void erase(int k) {        erase(root,k);    }    int getMin(int x) {        while(ch[x][0])            x=ch[x][0];        return x;    }    int getMax(int x) {        while(ch[x][1])            x=ch[x][1];        return x;    }    int getLow() {        if(size[root]==0)            return 0;        int x=getMin(root),ret=val[x];        erase(key[x]);        return ret;    }    int getHigh() {        if(size[root]==0)            return 0;        int x=getMax(root),ret=val[x];        erase(key[x]);        return ret;    }} treap;int main() {    int op,k,p;    while(~scanf("%d",&op)&&op)        switch(op) {        case 1:            scanf("%d%d",&k,&p);            treap.insert(p,k);            break;        case 2:            printf("%d\n",treap.getHigh());            break;        case 3:            printf("%d\n",treap.getLow());            break;        }}
#include<cstdio>using namespace std;const int MAXN=1000005;struct SBT {    int root,tot;    int ch[MAXN][2],key[MAXN],size[MAXN],val[MAXN];    SBT() {        tot=1;        root=0;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    void Maintain(int &x,int t) {        if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])            rotate(x,t);        else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {            rotate(ch[x][t],t^1);            rotate(x,t);        } else            return;        Maintain(ch[x][0],0);        Maintain(ch[x][1],1);        Maintain(x,0);        Maintain(x,1);    }    void insert(int &x,int k,int v) {        if(x==0) {            x=tot++;            ch[x][0]=ch[x][1]=0;            key[x]=k;            val[x]=v;            size[x]=1;        } else {            ++size[x];            insert(ch[x][k>=key[x]],k,v);            Maintain(x,k>=key[x]);        }    }    int erase(int &x,int k) {        --size[x];        if(key[x]==k||(k<key[x]&&ch[x][0]==0)||(k>key[x]&&ch[x][1]==0)) {            int ret=key[x];            if(ch[x][0]&&ch[x][1])                key[x]=erase(ch[x][0],key[x]+1);            else                x=ch[x][0]+ch[x][1];        } else            return erase(ch[x][k>=key[x]],k);    }    void insert(int k,int v) {        insert(root,k,v);    }    void erase(int k) {        erase(root,k);    }    int getMin(int x) {        while(ch[x][0])            x=ch[x][0];        return x;    }    int getMax(int x) {        while(ch[x][1])            x=ch[x][1];        return x;    }    int getLow() {        if(size[root]==0)            return 0;        int x=getMin(root),ret=val[x];        erase(key[x]);        return ret;    }    int getHigh() {        if(size[root]==0)            return 0;        int x=getMax(root),ret=val[x];        erase(key[x]);        return ret;    }} sbt;int main() {    int op,k,p;    while(~scanf("%d",&op)&&op)        switch(op) {        case 1:            scanf("%d%d",&k,&p);            sbt.insert(p,k);            break;        case 2:            printf("%d\n",sbt.getHigh());            break;        case 3:            printf("%d\n",sbt.getLow());            break;        }}
#include<cstdio>#include<cstdlib>using namespace std;const int MAX_LEVEL=18;struct SkipList {    struct node {        int key,val;        node *next[1];    };    int level;    node *head;    SkipList() {        level=0;        head=newNode(MAX_LEVEL-1,0,0);        for(int i=0; i<MAX_LEVEL; ++i)            head->next[i]=NULL;    }    node* newNode(int level,int key,int val) {        node *ns=(node *)malloc(sizeof(node)+level*sizeof(node*));        ns->key=key;        ns->val=val;        return ns;    }    int randomLevel() {        int k=1;        while(rand()&1)            ++k;        return k<MAX_LEVEL?k:MAX_LEVEL;    }    bool insert(int key,int val) {        node *update[MAX_LEVEL],*p=head,*q=NULL;        for(int i=level-1; i>=0; --i) {            while((q=p->next[i])&&q->key<key)                p=q;            update[i]=p;        }        if(q&&q->key==key)            return false;        int k=randomLevel();        if(k>level) {            for(int i=level; i<k; ++i)                update[i]=head;            level=k;        }        q=newNode(k,key,val);        for(int i=0; i<k; ++i) {            q->next[i]=update[i]->next[i];            update[i]->next[i]=q;        }        return true;    }    bool erase(int key) {        node *update[MAX_LEVEL],*p=head,*q=NULL;        for(int i=level-1; i>=0; --i) {            while((q=p->next[i])&&q->key<key)                p=q;            update[i]=p;        }        if(q&&q->key==key) {            for(int i=0; i<level; ++i)                if(update[i]->next[i]==q)                    update[i]->next[i]=q->next[i];            free(q);            for(int i=level-1; i>=0; --i)                if(!head->next[i])                    --level;            return true;        }        return false;    }    int getLow() {        node *p=head->next[0];        if(!p)            return 0;        int ret=p->val;        erase(p->key);        return ret;    }    int getHigh() {        node *p=head,*q=NULL;        for(int i=level-1; i>=0; --i)            while((q=p->next[i])&&q)                p=q;        if(p==head)            return 0;        int ret=p->val;        erase(p->key);        return ret;    }} sl;int main() {    int op,k,p;    while(~scanf("%d",&op)&&op)        switch(op) {        case 1:            scanf("%d%d",&k,&p);            sl.insert(p,k);            break;        case 2:            printf("%d\n",sl.getHigh());            break;        case 3:            printf("%d\n",sl.getLow());            break;        }}

  POJ1442

  难度一颗星;平衡树插入、求第k小。Treap、Size Balanced Tree各一发。

#include<cstdio>#include<cstdlib>using namespace std;const int MAXN=30005;const int INF=0x3f3f3f3f;struct Treap {    int tot,root;    int ch[MAXN][2],key[MAXN],pt[MAXN],size[MAXN];    Treap() {        tot=1;        root=0;        pt[0]=INF;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    bool insert(int &x,int k) {        if(!x) {            x=tot++;            ch[x][0]=ch[x][1]=0;            key[x]=k;            pt[x]=rand();            size[x]=1;        } else {            int t=key[x]<k;            ++size[x];            insert(ch[x][t],k);            if(pt[ch[x][t]]<pt[x])                rotate(x,t);        }    }    void insert(int k) {        insert(root,k);    }    int getKth(int k) {        int x=root;        while(size[ch[x][0]]+1!=k)            if(k<size[ch[x][0]]+1)                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }        return key[x];    }};int a[MAXN],u[MAXN];int main() {    int m,n;    while(~scanf("%d%d",&m,&n)) {        Treap treap;        for(int i=1; i<=m; ++i)            scanf("%d",&a[i]);        for(int i=0; i<n; ++i)            scanf("%d",&u[i]);        int pos=0;        for(int i=1; i<=m; ++i) {            treap.insert(a[i]);            while(i==u[pos])                printf("%d\n",treap.getKth(++pos));        }    }}
#include<cstdio>using namespace std;const int MAXN=30005;struct SBT {    int root,tot;    int ch[MAXN][2],key[MAXN],size[MAXN];    SBT() {        tot=1;        root=0;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    void Maintain(int &x,int t) {        if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])            rotate(x,t);        else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {            rotate(ch[x][t],t^1);            rotate(x,t);        }        else            return;        Maintain(ch[x][0],0);        Maintain(ch[x][1],1);        Maintain(x,0);        Maintain(x,1);    }    void insert(int &x,int k) {        if(!x) {            x=tot++;            ch[x][0]=ch[x][1]=0;            key[x]=k;            size[x]=1;        } else {            ++size[x];            insert(ch[x][key[x]<k],k);            Maintain(x,key[x]<k);        }    }    void insert(int k) {        insert(root,k);    }    int getKth(int k) {        int x=root;        while(size[ch[x][0]]+1!=k)            if(k<size[ch[x][0]]+1)                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }        return key[x];    }};int a[MAXN],u[MAXN];int main() {    int m,n;    while(~scanf("%d%d",&m,&n)) {        SBT sbt;        for(int i=1; i<=m; ++i)            scanf("%d",&a[i]);        for(int i=0; i<n; ++i)            scanf("%d",&u[i]);        int pos=0;        for(int i=1; i<=m; ++i) {            sbt.insert(a[i]);            while(i==u[pos])                printf("%d\n",sbt.getKth(++pos));        }    }}

  SPOJ3273

  难度一星半;平衡树插入、删除、求第k小,求排名。Treap、两种姿势Size Balanced Tree各一发。

#include<cstdio>#include<cstdlib>using namespace std;const int MAXN=200005;const int INF=0x3f3f3f3f;struct Treap {    int tot,root;    int ch[MAXN][2],key[MAXN],pt[MAXN],size[MAXN];    Treap() {        tot=1;        root=0;        pt[0]=INF;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    bool insert(int &x,int k) {        if(!x) {            x=tot++;            ch[x][0]=ch[x][1]=0;            key[x]=k;            pt[x]=rand();            size[x]=1;            return true;        }        if(key[x]==k)            return false;        int t=key[x]<k;        if(!insert(ch[x][t],k))            return false;        ++size[x];        if(pt[ch[x][t]]<pt[x])            rotate(x,t);        return true;    }    bool remove(int &x,int k) {        if(!x)            return false;        if(key[x]!=k) {            if(!remove(ch[x][key[x]<k],k))                return false;            --size[x];        } else if(!ch[x][0]&&!ch[x][1])            x=0;        else if(!ch[x][0])            x=ch[x][1];        else if(!ch[x][1])            x=ch[x][0];        else {            rotate(x,pt[ch[x][0]]>pt[ch[x][1]]);            if(!remove(ch[x][key[x]<k],k))                return false;            --size[x];        }        return true;    }    void insert(int k) {        insert(root,k);    }    void remove(int k) {        remove(root,k);    }    int getKth(int k) {        int x=root;        while(size[ch[x][0]]+1!=k)            if(k<size[ch[x][0]]+1)                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }        return key[x];    }    int getRank(int k) {        int ret=0,x=root;        while(x)            if(k<key[x])                x=ch[x][0];            else {                ret+=size[ch[x][0]]+1;                x=ch[x][1];            }        return ret;    }} treap;int main() {    int n,num;    char c;    scanf("%d",&n);    while(n--) {        scanf(" %c%d",&c,&num);        switch(c) {        case 'I':            treap.insert(num);            break;        case 'D':            treap.remove(num);            break;        case 'K':            num<=treap.size[treap.root]?printf("%d\n",treap.getKth(num)):puts("invalid");            break;        case 'C':            printf("%d\n",treap.getRank(num-1));            break;        }    }}
#include<cstdio>using namespace std;const int MAXN=200005;struct SBT {    int root,tot;    int ch[MAXN][2],key[MAXN],size[MAXN];    SBT() {        tot=1;        root=0;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    void Maintain(int &x,int t) {        if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])            rotate(x,t);        else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {            rotate(ch[x][t],t^1);            rotate(x,t);        } else            return;        Maintain(ch[x][0],0);        Maintain(ch[x][1],1);        Maintain(x,0);        Maintain(x,1);    }    bool insert(int &x,int k) {        if(!x) {            x=tot++;            ch[x][0]=ch[x][1]=0;            key[x]=k;            size[x]=1;            return true;        }        if(key[x]==k)            return false;        int t=k>=key[x];        if(!insert(ch[x][t],k))            return false;        ++size[x];        Maintain(x,t);        return true;    }    bool remove(int &x,int k) {        if(!x)            return false;        int t;        if(key[x]==k) {            if(!ch[x][1]) {                x=ch[x][0];                return true;            }            if(!ch[x][0]) {                x=ch[x][1];                return true;            }            int r=ch[x][1];            while(ch[r][0])                r=ch[r][0];            key[x]=key[r];            remove(ch[x][1],key[r]);            t=0;        } else {            t=k<key[x];            remove(ch[x][t^1],k);        }        Maintain(x,t);        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        return true;    }    void insert(int k) {        insert(root,k);    }    void remove(int k) {        remove(root,k);    }    int getKth(int k) {        int x=root;        while(size[ch[x][0]]+1!=k)            if(k<size[ch[x][0]]+1)                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }        return key[x];    }    int getRank(int k) {        int ret=0,x=root;        while(x)            if(k<key[x])                x=ch[x][0];            else {                ret+=size[ch[x][0]]+1;                x=ch[x][1];            }        return ret;    }} sbt;int main() {    int n,num;    char c;    scanf("%d",&n);    while(n--) {        scanf(" %c%d",&c,&num);        switch(c) {        case 'I':            sbt.insert(num);            break;        case 'D':            sbt.remove(num);            break;        case 'K':            num<=sbt.size[sbt.root]?printf("%d\n",sbt.getKth(num)):puts("invalid");            break;        case 'C':            printf("%d\n",sbt.getRank(num-1));            break;        }    }}
#include<cstdio>using namespace std;const int MAXN=200005;struct SBT {    int root,tot;    int ch[MAXN][2],key[MAXN],size[MAXN];    SBT() {        tot=1;        root=0;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    void Maintain(int &x,int t) {        if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])            rotate(x,t);        else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {            rotate(ch[x][t],t^1);            rotate(x,t);        } else            return;        Maintain(ch[x][0],0);        Maintain(ch[x][1],1);        Maintain(x,0);        Maintain(x,1);    }    void insert(int &x,int k) {        if(!x) {            x=tot++;            ch[x][0]=ch[x][1]=0;            key[x]=k;            size[x]=1;        } else {            ++size[x];            insert(ch[x][key[x]<k],k);            Maintain(x,key[x]<k);        }    }    int remove(int &x,int k) {        --size[x];        if(key[x]==k||(key[x]>k&&ch[x][0]==0)||(key[x]<k&&ch[x][1]==0)) {            int ret=key[x];            if(ch[x][0]&&ch[x][1])                key[x]=remove(ch[x][0],key[x]+1);            else                x=ch[x][0]+ch[x][1];            return ret;        }        return remove(ch[x][key[x]<k],k);    }    bool find(int x,int k) {        while(x) {            if(key[x]==k)                return true;            x=ch[x][key[x]<k];        }        return false;    }    void insert(int k) {        if(!find(root,k))            insert(root,k);    }    void remove(int k) {        if(find(root,k))            remove(root,k);    }    int getKth(int k) {        int x=root;        while(size[ch[x][0]]+1!=k)            if(k<size[ch[x][0]]+1)                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }        return key[x];    }    int getRank(int k) {        int ret=0,x=root;        while(x)            if(k<key[x])                x=ch[x][0];            else {                ret+=size[ch[x][0]]+1;                x=ch[x][1];            }        return ret;    }} sbt;int main() {    int n,num;    char c;    scanf("%d",&n);    while(n--) {        scanf(" %c%d",&c,&num);        switch(c) {        case 'I':            sbt.insert(num);            break;        case 'D':            sbt.remove(num);            break;        case 'K':            num<=sbt.size[sbt.root]?printf("%d\n",sbt.getKth(num)):puts("invalid");            break;        case 'C':            printf("%d\n",sbt.getRank(num-1));            break;        }    }}

  BZOJ1588

  难度一颗星;平衡树插入、求前驱、求后继。两种姿势Treap、两种姿势Size Balanced Tree各一发。

#include<cstdio>#include<algorithm>using namespace std;const int MAXN=40005;const int INF=0x3f3f3f3f;struct Treap {    int tot,root;    int ch[MAXN][2],key[MAXN],pt[MAXN],cnt[MAXN],size[MAXN];    Treap() {        tot=root=0;        pt[0]=INF;        size[0]=0;    }    void update(int x) {        size[x]=size[ch[x][0]]+cnt[x]+size[ch[x][1]];    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        update(x);        update(y);        x=y;    }    void insert(int &x,int k) {        if(x) {            if(key[x]==k)                ++cnt[x];            else {                int t=key[x]<k;                insert(ch[x][t],k);                if(pt[ch[x][t]]<pt[x])                    rotate(x,t);            }        } else {            x=++tot;            ch[x][0]=ch[x][1]=0;            key[x]=k;            pt[x]=rand();            cnt[x]=1;        }        update(x);    }    void insert(int k) {        insert(root,k);    }    int getPre(int x,int y,int k) {        if(x==0)            return y;        if(k==key[x]&&cnt[x]>1)            return x;        if(k>key[x])            return getPre(ch[x][1],x,k);        else            return getPre(ch[x][0],y,k);    }    int getNext(int x,int y,int k) {        if(x==0)            return y;        if(k==key[x]&&cnt[x]>1)            return x;        if(k<key[x])            getNext(ch[x][0],x,k);        else            getNext(ch[x][1],y,k);    }    int getPre(int k) {        return getPre(root,0,k);    }    int getNext(int k) {        return getNext(root,0,k);    }    int sigma(int k) {        int pre=getPre(k),next=getNext(k),ret=INF;        if(pre)            ret=min(ret,k-key[pre]);        if(next)            ret=min(ret,key[next]-k);        return ret==INF?k:ret;    }};int main() {    int n,x;    while(~scanf("%d",&n)) {        Treap treap;        int ans=0;        while(n--) {            if(!~scanf("%d",&x))                x=0;            treap.insert(x);            ans+=treap.sigma(x);        }        printf("%d\n",ans);    }}
#include<cstdio>#include<algorithm>using namespace std;const int MAXN=40005;const int INF=0x3f3f3f3f;struct Treap {    int tot,root;    int ch[MAXN][2],key[MAXN],pt[MAXN],size[MAXN];    Treap() {        tot=root=0;        pt[0]=INF;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    bool insert(int &x,int k) {        if(!x) {            x=++tot;            ch[x][0]=ch[x][1]=0;            key[x]=k;            pt[x]=rand();            size[x]=1;            return true;        }        if(key[x]==k)            return false;        int t=key[x]<k;        if(!insert(ch[x][t],k))            return false;        ++size[x];        if(pt[ch[x][t]]<pt[x])            rotate(x,t);        return true;    }    bool insert(int k) {        return insert(root,k);    }    int getPre(int x,int y,int k) {        if(x==0)            return y;        if(k>key[x])            return getPre(ch[x][1],x,k);        else            return getPre(ch[x][0],y,k);    }    int getNext(int x,int y,int k) {        if(x==0)            return y;        if(k<key[x])            return getNext(ch[x][0],x,k);        else            return getNext(ch[x][1],y,k);    }    int getPre(int k) {        return getPre(root,0,k);    }    int getNext(int k) {        return getNext(root,0,k);    }    int sigma(int k) {        int pre=getPre(k),next=getNext(k),ret=INF;        if(pre)            ret=min(ret,k-key[pre]);        if(next)            ret=min(ret,key[next]-k);        return ret==INF?k:ret;    }};int main() {    int n,x;    while(~scanf("%d",&n)) {        Treap treap;        int ans=0;        while(n--) {            if(!~scanf("%d",&x))                x=0;            bool flag=treap.insert(x);            ans+=flag?treap.sigma(x):0;        }        printf("%d\n",ans);    }}
#include<cstdio>#include<algorithm>using namespace std;const int MAXN=40005;const int INF=0x3f3f3f3f;struct SBT {    int root,tot;    int ch[MAXN][2],key[MAXN],size[MAXN];    SBT() {        tot=root=0;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    void Maintain(int &x,int t) {        if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])            rotate(x,t);        else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {            rotate(ch[x][t],t^1);            rotate(x,t);        } else            return;        Maintain(ch[x][0],0);        Maintain(ch[x][1],1);        Maintain(x,0);        Maintain(x,1);    }    void insert(int &x,int k) {        if(!x) {            x=++tot;            ch[x][0]=ch[x][1]=0;            key[x]=k;            size[x]=1;        } else {            ++size[x];            insert(ch[x][key[x]<k],k);            Maintain(x,key[x]<k);        }    }    bool find(int &x,int k) {        if(!x)            return false;        if(key[x]==k)            return true;        return find(ch[x][key[x]<k],k);    }    int insert(int k) {        bool flag=find(root,k);        if(!flag)            insert(root,k);        return !flag;    }    int getPre(int x,int y,int k) {        if(x==0)            return y;        if(k>key[x])            return getPre(ch[x][1],x,k);        else            return getPre(ch[x][0],y,k);    }    int getNext(int x,int y,int k) {        if(x==0)            return y;        if(k<key[x])            return getNext(ch[x][0],x,k);        else            return getNext(ch[x][1],y,k);    }    int getPre(int k) {        return getPre(root,0,k);    }    int getNext(int k) {        return getNext(root,0,k);    }    int sigma(int k) {        int pre=getPre(k),next=getNext(k),ret=INF;        if(pre)            ret=min(ret,k-key[pre]);        if(next)            ret=min(ret,key[next]-k);        return ret==INF?k:ret;    }};int main() {    int n,x;    while(~scanf("%d",&n)) {        SBT sbt;        int ans=0;        while(n--) {            if(!~scanf("%d",&x))                x=0;            bool flag=sbt.insert(x);            ans+=flag?sbt.sigma(x):0;        }        printf("%d\n",ans);    }}
#include<cstdio>#include<algorithm>using namespace std;const int MAXN=40005;const int INF=0x3f3f3f3f;struct SBT {    int root,tot;    int ch[MAXN][2],key[MAXN],size[MAXN];    SBT() {        tot=root=0;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    void Maintain(int &x,int t) {        if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])            rotate(x,t);        else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {            rotate(ch[x][t],t^1);            rotate(x,t);        } else            return;        Maintain(ch[x][0],0);        Maintain(ch[x][1],1);        Maintain(x,0);        Maintain(x,1);    }    bool insert(int &x,int k) {        if(!x) {            x=++tot;            ch[x][0]=ch[x][1]=0;            key[x]=k;            size[x]=1;            return true;        }        if(key[x]==k)            return false;        int t=key[x]<k;        if(!insert(ch[x][t],k))            return false;        ++size[x];        Maintain(x,t);        return true;    }    bool insert(int k) {        return insert(root,k);    }    int getPre(int x,int y,int k) {        if(x==0)            return y;        if(k>key[x])            return getPre(ch[x][1],x,k);        else            return getPre(ch[x][0],y,k);    }    int getNext(int x,int y,int k) {        if(x==0)            return y;        if(k<key[x])            return getNext(ch[x][0],x,k);        else            return getNext(ch[x][1],y,k);    }    int getPre(int k) {        return getPre(root,0,k);    }    int getNext(int k) {        return getNext(root,0,k);    }    int sigma(int k) {        int pre=getPre(k),next=getNext(k),ret=INF;        if(pre)            ret=min(ret,k-key[pre]);        if(next)            ret=min(ret,key[next]-k);        return ret==INF?k:ret;    }};int main() {    int n,x;    while(~scanf("%d",&n)) {        SBT sbt;        int ans=0;        while(n--) {            if(!~scanf("%d",&x))                x=0;            bool flag=sbt.insert(x);            ans+=flag?sbt.sigma(x):0;        }        printf("%d\n",ans);    }}

  BZOJ1208

  难度一星半;平衡树插入、删除、求前驱、求后继。两种姿势Treap、两种姿势Size Balanced Tree各一发。

#include<cstdio>#include<algorithm>using namespace std;const int MAXN=80005;const int INF=0x7fffffff;const int MOD=1000000;struct Treap {    int tot,root;    int ch[MAXN][2],key[MAXN],pt[MAXN],cnt[MAXN],size[MAXN];    Treap() {        tot=root=0;        pt[0]=INF;        size[0]=0;    }    void update(int x) {        size[x]=size[ch[x][0]]+cnt[x]+size[ch[x][1]];    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        update(x);        update(y);        x=y;    }    void insert(int &x,int k) {        if(x) {            if(key[x]==k)                ++cnt[x];            else {                int t=key[x]<k;                insert(ch[x][t],k);                if(pt[ch[x][t]]<pt[x])                    rotate(x,t);            }        } else {            x=++tot;            ch[x][0]=ch[x][1]=0;            key[x]=k;            pt[x]=rand();            cnt[x]=1;        }        update(x);    }    void erase(int &x,int k) {        if(key[x]==k) {            if(cnt[x]>1)                --cnt[x];            else {                if(!ch[x][0]&&!ch[x][1]) {                    x=0;                    return;                }                rotate(x,pt[ch[x][0]]>pt[ch[x][1]]);                erase(x,k);            }        } else            erase(ch[x][key[x]<k],k);        update(x);    }    int getPre(int x,int y,int k) {        if(x==0)            return y;        if(k>key[x])            return getPre(ch[x][1],x,k);        else            return getPre(ch[x][0],y,k);    }    int getNext(int x,int y,int k) {        if(x==0)            return y;        if(k<key[x])            return getNext(ch[x][0],x,k);        else            return getNext(ch[x][1],y,k);    }    void insert(int k) {        insert(root,k);    }    void erase(int k) {        erase(root,k);    }    int getPre(int k) {        return getPre(root,0,k);    }    int getNext(int k) {        return getNext(root,0,k);    }};int main() {    int n,a,b;    while(~scanf("%d",&n)) {        Treap treap;        int ans=0,status;        while(n--) {            scanf("%d%d",&a,&b);            if(treap.size[treap.root]==0)                status=a;            treap.insert(b);            if(status!=a) {                int pre=treap.getPre(b),next=treap.getNext(b),pv=INF,nv=INF;                if(pre)                    pv=b-treap.key[pre];                if(next)                    nv=treap.key[next]-b;                ans+=min(pv,nv);                ans%=MOD;                if(pv<=nv)                    treap.erase(treap.key[pre]);                else                    treap.erase(treap.key[next]);                treap.erase(b);            }        }        printf("%d\n",ans);    }}
#include<cstdio>#include<algorithm>using namespace std;const int MAXN=80005;const int INF=0x7fffffff;const int MOD=1000000;struct Treap {    int tot,root;    int ch[MAXN][2],key[MAXN],pt[MAXN],size[MAXN];    Treap() {        tot=root=0;        pt[0]=INF;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    bool insert(int &x,int k) {        if(!x) {            x=++tot;            ch[x][0]=ch[x][1]=0;            key[x]=k;            pt[x]=rand();            size[x]=1;            return true;        }        if(key[x]==k)            return false;        int t=key[x]<k;        if(!insert(ch[x][t],k))            return false;        ++size[x];        if(pt[ch[x][t]]<pt[x])            rotate(x,t);        return true;    }    bool erase(int &x,int k) {        if(!x)            return false;        if(key[x]!=k) {            if(!erase(ch[x][key[x]<k],k))                return false;            --size[x];        } else if(!ch[x][0]&&!ch[x][1])            x=0;        else if(!ch[x][0])            x=ch[x][1];        else if(!ch[x][1])            x=ch[x][0];        else {            rotate(x,pt[ch[x][0]]>pt[ch[x][1]]);            if(!erase(ch[x][key[x]<k],k))                return false;            --size[x];        }        return true;    }    int getPre(int x,int y,int k) {        if(x==0)            return y;        if(k>key[x])            return getPre(ch[x][1],x,k);        else            return getPre(ch[x][0],y,k);    }    int getNext(int x,int y,int k) {        if(x==0)            return y;        if(k<key[x])            return getNext(ch[x][0],x,k);        else            return getNext(ch[x][1],y,k);    }    void insert(int k) {        insert(root,k);    }    void erase(int k) {        erase(root,k);    }    int getPre(int k) {        return getPre(root,0,k);    }    int getNext(int k) {        return getNext(root,0,k);    }};int main() {    int n,a,b;    while(~scanf("%d",&n)) {        Treap treap;        int ans=0,status;        while(n--) {            scanf("%d%d",&a,&b);            if(treap.size[treap.root]==0)                status=a;            treap.insert(b);            if(status!=a) {                int pre=treap.getPre(b),next=treap.getNext(b),pv=INF,nv=INF;                if(pre)                    pv=b-treap.key[pre];                if(next)                    nv=treap.key[next]-b;                ans+=min(pv,nv);                ans%=MOD;                if(pv<=nv)                    treap.erase(treap.key[pre]);                else                    treap.erase(treap.key[next]);                treap.erase(b);            }        }        printf("%d\n",ans);    }}
#include<cstdio>#include<algorithm>using namespace std;const int MAXN=80005;const int INF=0x7fffffff;const int MOD=1000000;struct SBT {    int root,tot;    int ch[MAXN][2],key[MAXN],size[MAXN];    SBT() {        tot=root=0;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    void Maintain(int &x,int t) {        if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])            rotate(x,t);        else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {            rotate(ch[x][t],t^1);            rotate(x,t);        } else            return;        Maintain(ch[x][0],0);        Maintain(ch[x][1],1);        Maintain(x,0);        Maintain(x,1);    }    void insert(int &x,int k) {        if(!x) {            x=++tot;            ch[x][0]=ch[x][1]=0;            key[x]=k;            size[x]=1;        } else {            ++size[x];            insert(ch[x][key[x]<k],k);            Maintain(x,key[x]<k);        }    }    int erase(int &x,int k) {        --size[x];        if(key[x]==k||(key[x]>k&&ch[x][0]==0)||(key[x]<k&&ch[x][1]==0)) {            int ret=key[x];            if(ch[x][0]&&ch[x][1])                key[x]=erase(ch[x][0],key[x]+1);            else                x=ch[x][0]+ch[x][1];            return ret;        }        return erase(ch[x][key[x]<k],k);    }    int getPre(int x,int y,int k) {        if(x==0)            return y;        if(k>key[x])            return getPre(ch[x][1],x,k);        else            return getPre(ch[x][0],y,k);    }    int getNext(int x,int y,int k) {        if(x==0)            return y;        if(k<key[x])            return getNext(ch[x][0],x,k);        else            return getNext(ch[x][1],y,k);    }    void insert(int k) {        insert(root,k);    }    void erase(int k) {        erase(root,k);    }    int getPre(int k) {        return getPre(root,0,k);    }    int getNext(int k) {        return getNext(root,0,k);    }};int main() {    int n,a,b;    while(~scanf("%d",&n)) {        SBT sbt;        int ans=0,status;        while(n--) {            scanf("%d%d",&a,&b);            if(sbt.size[sbt.root]==0)                status=a;            sbt.insert(b);            if(status!=a) {                int pre=sbt.getPre(b),next=sbt.getNext(b),pv=INF,nv=INF;                if(pre)                    pv=b-sbt.key[pre];                if(next)                    nv=sbt.key[next]-b;                ans+=min(pv,nv);                ans%=MOD;                if(pv<=nv)                    sbt.erase(sbt.key[pre]);                else                    sbt.erase(sbt.key[next]);                sbt.erase(b);            }        }        printf("%d\n",ans);    }}
#include<cstdio>#include<algorithm>using namespace std;const int MAXN=80005;const int INF=0x7fffffff;const int MOD=1000000;struct SBT {    int root,tot;    int ch[MAXN][2],key[MAXN],size[MAXN];    SBT() {        tot=root=0;        size[0]=0;    }    void rotate(int &x,int t) {        int y=ch[x][t];        ch[x][t]=ch[y][t^1];        ch[y][t^1]=x;        size[y]=size[x];        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        x=y;    }    void Maintain(int &x,int t) {        if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])            rotate(x,t);        else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {            rotate(ch[x][t],t^1);            rotate(x,t);        } else            return;        Maintain(ch[x][0],0);        Maintain(ch[x][1],1);        Maintain(x,0);        Maintain(x,1);    }    bool insert(int &x,int k) {        if(!x) {            x=++tot;            ch[x][0]=ch[x][1]=0;            key[x]=k;            size[x]=1;            return true;        }        if(key[x]==k)            return false;        int t=key[x]<k;        if(!insert(ch[x][t],k))            return false;        ++size[x];        Maintain(x,t);        return true;    }    bool erase(int &x,int k) {        if(!x)            return false;        int t;        if(key[x]==k) {            if(!ch[x][1]) {                x=ch[x][0];                return true;            }            if(!ch[x][0]) {                x=ch[x][1];                return true;            }            int r=ch[x][1];            while(ch[r][0])                r=ch[r][0];            key[x]=key[r];            erase(ch[x][1],key[r]);            t=0;        } else {            t=k<key[x];            erase(ch[x][t^1],k);        }        Maintain(x,t);        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;        return true;    }    int getPre(int x,int y,int k) {        if(x==0)            return y;        if(k>key[x])            return getPre(ch[x][1],x,k);        else            return getPre(ch[x][0],y,k);    }    int getNext(int x,int y,int k) {        if(x==0)            return y;        if(k<key[x])            return getNext(ch[x][0],x,k);        else            return getNext(ch[x][1],y,k);    }    void insert(int k) {        insert(root,k);    }    void erase(int k) {        erase(root,k);    }    int getPre(int k) {        return getPre(root,0,k);    }    int getNext(int k) {        return getNext(root,0,k);    }};int main() {    int n,a,b;    while(~scanf("%d",&n)) {        SBT sbt;        int ans=0,status;        while(n--) {            scanf("%d%d",&a,&b);            if(sbt.size[sbt.root]==0)                status=a;            sbt.insert(b);            if(status!=a) {                int pre=sbt.getPre(b),next=sbt.getNext(b),pv=INF,nv=INF;                if(pre)                    pv=b-sbt.key[pre];                if(next)                    nv=sbt.key[next]-b;                ans+=min(pv,nv);                ans%=MOD;                if(pv<=nv)                    sbt.erase(sbt.key[pre]);                else                    sbt.erase(sbt.key[next]);                sbt.erase(b);            }        }        printf("%d\n",ans);    }}

  HDU1890

  难度两颗星;区间翻转。两种姿势Splay各一发。

#include<cstdio>#include<algorithm>using namespace std;const int MAXN=100005;pair<int,int> p[MAXN];struct Splay {    int root;    int ch[MAXN][2],pre[MAXN],size[MAXN];    void rotate(int x,int f) {        int y=pre[x];        ch[y][f^1]=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;        push_up(y);    }    void splay(int x,int goal) {        push_down(x);        while(pre[x]!=goal) {            int y=pre[x],z=pre[y];            if(z==goal) {                push_down(y);                push_down(x);                rotate(x,ch[y][0]==x);            } else {                push_down(z);                push_down(y);                push_down(x);                int f=ch[z][0]==y;                if(ch[y][f]==x)                    rotate(x,f^1);                else                    rotate(y,f);                rotate(x,f);            }        }        push_up(x);        if(goal==0)            root=x;    }    void rotate_to(int k,int goal) {        int x=root;        push_down(x);        while(size[ch[x][0]]+1!=k) {            if(k<size[ch[x][0]]+1)                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }            push_down(x);        }        splay(x,goal);    }    void NewNode(int x,int fa) {        ch[x][0]=ch[x][1]=0;        size[x]=1;        pre[x]=fa;        rev[x]=0;    }    void push_up(int x) {        size[x]=size[ch[x][0]]+1+size[ch[x][1]];    }    void push_down(int x) {        if(rev[x]) {            rev[ch[x][0]]^=1;            rev[ch[x][1]]^=1;            swap(ch[x][0],ch[x][1]);            rev[x]=0;        }    }    void build(int &x,int l,int r,int f) {        if(l>r)            return;        int m=l+r>>1;        x=m;        NewNode(x,f);        build(ch[x][0],l,m-1,x);        build(ch[x][1],m+1,r,x);        push_up(x);    }    void erase(int x) {        int y=pre[x];        if(!ch[x][0]) {            ch[y][ch[y][1]==x]=ch[x][1];            pre[ch[x][1]]=y;        } else {            int z=ch[x][0];            push_down(z);            while(ch[z][1]) {                z=ch[z][1];                push_down(z);            }            splay(z,y);            ch[z][1]=ch[x][1];            pre[ch[x][1]]=z;            ch[y][ch[y][1]==x]=z;            pre[z]=y;        }    }    void init(int n) {        root=0;        ch[0][0]=ch[0][1]=pre[0]=size[0]=0;        rev[0]=0;        build(root,1,n,0);    }    void solve(int n) {        init(n);        for(int i=1; i<=n; ++i) {            splay(p[i].second,0);            if(i>1)                putchar(' ');            printf("%d",i+size[ch[root][0]]);            rev[ch[root][0]]^=1;            erase(root);        }        putchar('\n');    }    int rev[MAXN];} splay;int main() {    int n;    while(~scanf("%d",&n)&&n) {        for(int i=1; i<=n; ++i) {            scanf("%d",&p[i].first);            p[i].second=i;        }        sort(p+1,p+n+1);        splay.solve(n);    }}
#include<cstdio>#include<algorithm>using namespace std;#define keyTree ch[ch[root][1]][0]const int MAXN=100005;pair<int,int> p[MAXN];struct Splay {    int root;    int ch[MAXN][2],pre[MAXN],size[MAXN];    void rotate(int x,int f) {        int y=pre[x];        ch[y][f^1]=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;        push_up(y);    }    void splay(int x,int goal) {        push_down(x);        while(pre[x]!=goal) {            int y=pre[x],z=pre[y];            if(z==goal) {                push_down(y);                push_down(x);                rotate(x,ch[y][0]==x);            } else {                push_down(z);                push_down(y);                push_down(x);                int f=ch[z][0]==y;                if(ch[y][f]==x)                    rotate(x,f^1);                else                    rotate(y,f);                rotate(x,f);            }        }        push_up(x);        if(goal==0)            root=x;    }    void rotate_to(int k,int goal) {        int x=root;        push_down(x);        while(size[ch[x][0]]+1!=k) {            if(k<size[ch[x][0]]+1)                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }            push_down(x);        }        splay(x,goal);    }    void NewNode(int &x,int fa) {        ch[x][0]=ch[x][1]=0;        size[x]=1;        pre[x]=fa;        rev[x]=0;    }    void push_up(int x) {        size[x]=size[ch[x][0]]+1+size[ch[x][1]];    }    void push_down(int x) {        if(rev[x]) {            rev[ch[x][0]]^=1;            rev[ch[x][1]]^=1;            swap(ch[x][0],ch[x][1]);            rev[x]=0;        }    }    void build(int &x,int l,int r,int f) {        if(l>r)            return;        int m=l+r>>1;        x=m;        NewNode(x,f);        build(ch[x][0],l,m-1,x);        build(ch[x][1],m+1,r,x);        push_up(x);    }    void init(int n) {        ch[0][0]=ch[0][1]=size[0]=0;        rev[0]=0;        root=n+1;        NewNode(root,0);        ch[root][1]=n+2;        NewNode(ch[root][1],root);        size[root]=2;        build(keyTree,1,n,ch[root][1]);        push_up(ch[root][1]);        push_up(root);    }    int get_next(int x) {        push_down(x);        if(ch[x][1]==0)            return -1;        x=ch[x][1];        while(ch[x][0]) {            x=ch[x][0];            push_down(x);        }        return x;    }    void solve(int n) {        init(n);        for(int i=1; i<=n; ++i) {            splay(p[i].second,0);            if(i>1)                putchar(' ');            printf("%d",size[ch[root][0]]);            rotate_to(i,0);            splay(get_next(p[i].second),root);            rev[keyTree]^=1;            push_up(ch[root][1]);            push_up(root);        }        putchar('\n');    }    int rev[MAXN];} splay;int main() {    int n;    while(~scanf("%d",&n)&&n) {        for(int i=1; i<=n; ++i) {            scanf("%d",&p[i].first);            p[i].second=i;        }        sort(p+1,p+n+1);        splay.solve(n);    }}

  HDU3436

  难度两颗星;节点移动,平衡树求第k小,求排名。Splay一发。

#include<cstdio>#include<algorithm>using namespace std;const int MAXN=100005;char op[MAXN][10];int data[MAXN],hash[MAXN],bg[MAXN<<1],ed[MAXN<<1],cnt;int bi_search(int x) {    int l=0,r=cnt-1;    while(l<=r) {        int m=l+r>>1;        if(bg[m]<=x&&ed[m]>=x)            return m;        if(ed[m]<x)            l=m+1;        else            r=m-1;    }}struct SplayTree {    int root,tot;    int ch[MAXN<<1][2],pre[MAXN<<1],size[MAXN<<1];    void rotate(int x,int f) {        int y=pre[x];        ch[y][f^1]=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;        push_up(y);    }    void splay(int x,int goal) {        while(pre[x]!=goal)            if(pre[pre[x]]==goal)                rotate(x,ch[pre[x]][0]==x);            else {                int y=pre[x],z=pre[y],f=ch[z][0]==y;                if(ch[y][f]==x)                    rotate(x,f^1);                else                    rotate(y,f);                rotate(x,f);            }        push_up(x);        if(goal==0)            root=x;    }    void rotate_to(int k,int goal) {        int x=root;        while(size[ch[x][0]]+1!=k)            if(k<size[ch[x][0]]+1)                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }        splay(x,goal);    }    void NewNode(int &x,int fa,int k) {        x=++tot;        ch[x][0]=ch[x][1]=0;        size[x]=num[x]=ed[k]-bg[k]+1;        pre[x]=fa;        key[x]=k;        node[k]=x;    }    void push_up(int x) {        size[x]=size[ch[x][0]]+size[ch[x][1]]+num[x];    }    void build(int &x,int l,int r,int f) {        if(l>r)            return;        int m=l+r>>1;        NewNode(x,f,m);        build(ch[x][0],l,m-1,x);        build(ch[x][1],m+1,r,x);        push_up(x);    }    void init() {        root=tot=0;        ch[0][0]=ch[0][1]=size[0]=0;        build(root,0,cnt-1,0);    }    int get_rank(int x) {        int k=bi_search(x);        splay(node[k],0);        return size[ch[root][0]]+1;    }    int get_kth(int x,int k) {        int t=size[ch[x][0]];        if(t>=k)            return get_kth(ch[x][0],k);        else if(t+num[x]>=k)            return bg[key[x]]+k-t-1;        else            return get_kth(ch[x][1],k-t-num[x]);    }    void insert(int &x,int k,int fa) {        if(x==0) {            NewNode(x,fa,k);            splay(x,0);            return;        }        insert(ch[x][0],k,x);        push_up(x);    }    void del() {        int x=root;        if(ch[root][1]) {            root=ch[root][1];            rotate_to(1,0);            ch[root][0]=ch[x][0];            if(ch[root][0])                pre[ch[root][0]]=root;        } else            root=ch[root][0];        pre[root]=0;        push_up(root);    }    void top(int x) {        int k=bi_search(x);        splay(node[k],0);        del();        insert(root,k,0);        splay(node[k],0);    }    int key[MAXN<<1],num[MAXN<<1],node[MAXN<<1];} splay;int main() {    int t,n,q;    scanf("%d",&t);    for(int cas=1; cas<=t; ++cas) {        scanf("%d%d",&n,&q);        int tot=cnt=0;        hash[tot++]=0;        for(int i=0; i<q; ++i) {            scanf("%s%d",op[i],&data[i]);            if(op[i][0]!='R')                hash[tot++]=data[i];        }        hash[tot++]=n;        sort(hash,hash+tot);        tot=unique(hash,hash+tot)-hash;        for(int i=1; i<tot; ++i) {            if(hash[i]-hash[i-1]>1) {                bg[cnt]=hash[i-1]+1;                ed[cnt]=hash[i]-1;                ++cnt;            }            bg[cnt]=ed[cnt]=hash[i];            ++cnt;        }        printf("Case %d:\n",cas);        splay.init();        for(int i=0; i<q; ++i)            switch(op[i][0]) {            case 'T':                splay.top(data[i]);                break;            case 'Q':                printf("%d\n",splay.get_rank(data[i]));                break;            case 'R':                printf("%d\n",splay.get_kth(splay.root,data[i]));                break;            }    }}

  HDU3487

  难度两星半;区间分割(移动),区间翻转。Splay一发。

#include<cstdio>#include<algorithm>using namespace std;#define keyTree (ch[ch[root][1]][0])const int MAXN=300005;struct SplayTree {    int root,tot;    int ch[MAXN][2],pre[MAXN],size[MAXN];    void rotate(int x,int f) {        int y=pre[x];        ch[y][f^1]=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;        push_up(y);    }    void splay(int x,int goal) {        push_down(x);        while(pre[x]!=goal) {            int y=pre[x],z=pre[y];            if(z==goal) {                push_down(y);                push_down(x);                rotate(x,ch[y][0]==x);            } else {                push_down(z);                push_down(y);                push_down(x);                int f=ch[z][0]==y;                if(ch[y][f]==x)                    rotate(x,f^1);                else                    rotate(y,f);                rotate(x,f);            }        }        push_up(x);        if(goal==0)            root=x;    }    void rotate_to(int k,int goal) {        int x=root;        push_down(x);        while(size[ch[x][0]]!=k) {            if(k<size[ch[x][0]])                x=ch[x][0];            else {                k-=size[ch[x][0]]+1;                x=ch[x][1];            }            push_down(x);        }        splay(x,goal);    }    void NewNode(int &x,int c,int fa) {        x=++tot;        ch[x][0]=ch[x][1]=0;        size[x]=1;        pre[x]=fa;        key[x]=c;        rev[x]=0;    }    void push_up(int x) {        size[x]=1+size[ch[x][0]]+size[ch[x][1]];    }    void push_down(int x) {        if(rev[x]) {            rev[ch[x][0]]^=1;            rev[ch[x][1]]^=1;            swap(ch[x][0],ch[x][1]);            rev[x]=0;        }    }    void build(int &x,int l,int r,int f) {        if(l>r)            return;        int m=l+r>>1;        NewNode(x,m,f);        build(ch[x][0],l,m-1,x);        build(ch[x][1],m+1,r,x);        push_up(x);    }    void init(int n) {        root=tot=0;        ch[0][0]=ch[0][1]=size[0]=0;        rev[0]=0;        NewNode(root,-1,0);        NewNode(ch[root][1],-1,root);        size[root]=2;        build(keyTree,1,n,ch[root][1]);        push_up(ch[root][1]);        push_up(root);    }    void reverse(int l,int r) {        rotate_to(l-1,0);        rotate_to(r+1,root);        rev[keyTree]^=1;    }    void cut(int l,int r,int p) {        rotate_to(l-1,0);        rotate_to(r+1,root);        int tmp=keyTree;        keyTree=0;        push_up(ch[root][1]);        push_up(root);        rotate_to(p,0);        rotate_to(p+1,root);        keyTree=tmp;        pre[keyTree]=ch[root][1];        push_up(ch[root][1]);        push_up(root);    }    void InOrder(int x) {        if(!x)            return;        push_down(x);        InOrder(ch[x][0]);        if(key[x]!=-1) {            if(cnt>1)                putchar(' ');            printf("%d" ,key[x]);        }        ++cnt;        InOrder(ch[x][1]);    }    void output() {        cnt=0;        InOrder(root);        putchar('\n');    }    int key[MAXN],rev[MAXN],cnt;} splay;int main() {    int n,m,a,b,c;    char op[5];    while(~scanf("%d%d",&n,&m)&&~n&&~m) {        splay.init(n);        while(m--) {            scanf("%s%d%d",op,&a,&b);            switch(op[0]) {            case 'C':                scanf("%d",&c);                splay.cut(a,b,c);                break;            case 'F':                splay.reverse(a,b);                break;            }        }        splay.output();    }}

  ZOJ2112

  难度三星半;单点修改,区间第k小。树状数组+可持久化线段树(主席树)、两种姿势线段树+Treap各一发。

#include<cstdio>#include<algorithm>using namespace std;#define lson l,m,ls[rt]#define rson m+1,r,rs[rt]const int MAXN=60005;const int MAXM=2500005;int t,n,m,size;int ls[MAXM],rs[MAXM],cnt[MAXM],root[MAXN],tot;void build(int l,int r,int &rt) {    rt=tot++;    cnt[rt]=0;    if(l==r)        return;    int m=(l+r)>>1;    build(lson);    build(rson);}void update(int last,int p,int val,int l,int r,int &rt) {    rt=tot++;    ls[rt]=ls[last];    rs[rt]=rs[last];    cnt[rt]=cnt[last]+val;    if(l==r)        return;    int m=(l+r)>>1;    if(p<=m)        update(ls[last],p,val,lson);    else        update(rs[last],p,val,rson);}int bit[MAXN],use[MAXN];inline int lowbit(int x) {    return x&-x;}void modify(int x,int p,int val) {    for(int i=x; i<=n; i+=lowbit(i))        update(bit[i],p,val,1,size,bit[i]);}int sum(int x) {    int ret=0;    for(int i=x; i>0; i-=lowbit(i))        ret+=cnt[ls[use[i]]];    return ret;}int query(int ss,int tt,int l,int r,int k) {    for(int i=ss; i>0; i-=lowbit(i))        use[i]=bit[i];    for(int i=tt; i>0; i-=lowbit(i))        use[i]=bit[i];    int sr=root[ss],tr=root[tt];    while(l<r) {        int m=(l+r)>>1,tmp=sum(tt)-sum(ss)+cnt[ls[tr]]-cnt[ls[sr]];        if(k<=tmp) {            r=m;            for(int i=ss; i>0; i-=lowbit(i))                use[i]=ls[use[i]];            for(int i=tt; i>0; i-=lowbit(i))                use[i]=ls[use[i]];            sr=ls[sr];            tr=ls[tr];        } else {            l=m+1;            k-=tmp;            for(int i=ss; i>0; i-=lowbit(i))                use[i]=rs[use[i]];            for(int i=tt; i>0; i-=lowbit(i))                use[i]=rs[use[i]];            sr=rs[sr];            tr=rs[tr];        }    }    return l;}int num[MAXN],hash[MAXN],l[MAXN],r[MAXN],k[MAXN];char op[MAXN];int main() {    scanf("%d",&t);    while(t--) {        scanf("%d%d",&n,&m);        size=0;        for(int i=1; i<=n; ++i) {            scanf("%d",&num[i]);            hash[++size]=num[i];        }        for(int i=0; i<m; ++i) {            scanf(" %c%d%d",&op[i],&l[i],&r[i]);            switch(op[i]) {            case 'Q':                scanf("%d",&k[i]);                break;            case 'C':                hash[++size]=r[i];                break;            }        }        sort(hash+1,hash+size+1);        size=unique(hash+1,hash+size+1)-hash-1;        for(int i=1; i<=n; ++i)            num[i]=lower_bound(hash+1,hash+size+1,num[i])-hash;        tot=0;        build(1,size,root[0]);        for(int i=1; i<=n; ++i)            update(root[i-1],num[i],1,1,size,root[i]);        for(int i=1; i<=n; ++i)            bit[i]=root[0];        for(int i=0; i<m; ++i)            switch(op[i]) {            case 'Q':                printf("%d\n",hash[query(l[i]-1,r[i],1,size,k[i])]);                break;            case 'C':                modify(l[i],num[l[i]],-1);                num[l[i]]=lower_bound(hash+1,hash+size+1,r[i])-hash;                modify(l[i],num[l[i]],1);                break;            }    }}
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int MAXN=60005;const int MAXM=900005;const int INF=0x3f3f3f3f;int ch[MAXM][2],key[MAXM],pt[MAXM],cnt[MAXM],size[MAXM],tot,root;void init() {    tot=root=0;    pt[0]=-INF;    size[0]=0;}void update(int x) {    size[x]=size[ch[x][0]]+cnt[x]+size[ch[x][1]];}void rotate(int &x,int t) {    int y=ch[x][t];    ch[x][t]=ch[y][t^1];    ch[y][t^1]=x;    update(x);    update(y);    x=y;}void insert(int &x,int k) {    if(x) {        if(key[x]==k)            ++cnt[x];        else {            int t=key[x]<k;            insert(ch[x][t],k);            if(pt[ch[x][t]]>pt[x])                rotate(x,t);        }    } else {        x=++tot;        ch[x][0]=ch[x][1]=0;        key[x]=k;        pt[x]=rand();        cnt[x]=1;    }    update(x);}void erase(int &x,int k) {    if(key[x]==k) {        if(cnt[x]>1)            --cnt[x];        else {            if(!ch[x][0]&&!ch[x][1]) {                x=0;                return;            }            rotate(x,pt[ch[x][0]]<pt[ch[x][1]]);            erase(x,k);        }    } else        erase(ch[x][key[x]<k],k);    update(x);}int seg[MAXN<<2];int calc(int x,int k) {    if(!x)        return 0;    if(k<key[x])        return calc(ch[x][0],k);    else        return size[ch[x][0]]+cnt[x]+calc(ch[x][1],k);}void segins(int p,int val,int l,int r,int rt) {    insert(seg[rt],val);    if(l==r)        return;    int m=l+r>>1;    if(p<=m)        segins(p,val,lson);    else        segins(p,val,rson);}void segdel(int p,int val,int l,int r,int rt) {    erase(seg[rt],val);    if(l==r)        return;    int m=l+r>>1;    if(p<=m)        segdel(p,val,lson);    else        segdel(p,val,rson);}int query(int L,int R,int k,int l,int r,int rt) {    if(l==r)        return l;    int m=l+r>>1,cnt=calc(seg[rt<<1],R)-calc(seg[rt<<1],L);    if(k<=cnt)        return query(L,R,k,lson);    else        return query(L,R,k-cnt,rson);}int num[MAXN],hash[MAXN],l[MAXN],r[MAXN],k[MAXN];char op[MAXN];int main() {    int t,n,m;    scanf("%d",&t);    while(t--) {        scanf("%d%d",&n,&m);        int hs=0;        for(int i=1; i<=n; ++i) {            scanf("%d",&num[i]);            hash[++hs]=num[i];        }        for(int i=0; i<m; ++i) {            scanf(" %c%d%d",&op[i],&l[i],&r[i]);            switch(op[i]) {            case 'Q':                scanf("%d",&k[i]);                break;            case 'C':                hash[++hs]=r[i];                break;            }        }        sort(hash+1,hash+hs+1);        hs=unique(hash+1,hash+hs+1)-hash-1;        init();        memset(seg,0,sizeof(seg));        for(int i=1; i<=n; ++i) {            num[i]=lower_bound(hash+1,hash+hs+1,num[i])-hash;            segins(num[i],i,1,hs,1);        }        for(int i=0; i<m; ++i)            switch(op[i]) {            case 'Q':                printf("%d\n",hash[query(l[i]-1,r[i],k[i],1,hs,1)]);                break;            case 'C':                segdel(num[l[i]],l[i],1,hs,1);                num[l[i]]=lower_bound(hash+1,hash+hs+1,r[i])-hash;                segins(num[l[i]],l[i],1,hs,1);                break;            }    }}
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int MAXN=60005;const int MAXM=900005;const int INF=0x3f3f3f3f;int ch[MAXM][2],key[MAXM],pt[MAXM],size[MAXM],tot,root;void init() {    tot=root=0;    pt[0]=INF;    size[0]=0;}void rotate(int &x,int t) {    int y=ch[x][t];    ch[x][t]=ch[y][t^1];    ch[y][t^1]=x;    size[y]=size[x];    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;    x=y;}bool insert(int &x,int k) {    if(!x) {        x=++tot;        ch[x][0]=ch[x][1]=0;        key[x]=k;        pt[x]=rand();        size[x]=1;        return true;    }    if(key[x]==k)        return false;    int t=key[x]<k;    if(!insert(ch[x][t],k))        return false;    ++size[x];    if(pt[ch[x][t]]<pt[x])        rotate(x,t);    return true;}bool erase(int &x,int k) {    if(!x)        return false;    if(key[x]!=k) {        if(!erase(ch[x][key[x]<k],k))            return false;        --size[x];    } else if(!ch[x][0]&&!ch[x][1])        x=0;    else if(!ch[x][0])        x=ch[x][1];    else if(!ch[x][1])        x=ch[x][0];    else {        rotate(x,pt[ch[x][0]]>pt[ch[x][1]]);        if(!erase(ch[x][key[x]<k],k))            return false;        --size[x];    }    return true;}int seg[MAXN<<2];int calc(int x,int k) {    if(!x)        return 0;    if(k<key[x])        return calc(ch[x][0],k);    else        return size[ch[x][0]]+1+calc(ch[x][1],k);}void segins(int p,int val,int l,int r,int rt) {    insert(seg[rt],val);    if(l==r)        return;    int m=l+r>>1;    if(p<=m)        segins(p,val,lson);    else        segins(p,val,rson);}void segdel(int p,int val,int l,int r,int rt) {    erase(seg[rt],val);    if(l==r)        return;    int m=l+r>>1;    if(p<=m)        segdel(p,val,lson);    else        segdel(p,val,rson);}int query(int L,int R,int k,int l,int r,int rt) {    if(l==r)        return l;    int m=l+r>>1,cnt=calc(seg[rt<<1],R)-calc(seg[rt<<1],L);    if(k<=cnt)        return query(L,R,k,lson);    else        return query(L,R,k-cnt,rson);}int num[MAXN],hash[MAXN],l[MAXN],r[MAXN],k[MAXN];char op[MAXN];int main() {    int t,n,m;    scanf("%d",&t);    while(t--) {        scanf("%d%d",&n,&m);        int hs=0;        for(int i=1; i<=n; ++i) {            scanf("%d",&num[i]);            hash[++hs]=num[i];        }        for(int i=0; i<m; ++i) {            scanf(" %c%d%d",&op[i],&l[i],&r[i]);            switch(op[i]) {            case 'Q':                scanf("%d",&k[i]);                break;            case 'C':                hash[++hs]=r[i];                break;            }        }        sort(hash+1,hash+hs+1);        hs=unique(hash+1,hash+hs+1)-hash-1;        init();        memset(seg,0,sizeof(seg));        for(int i=1; i<=n; ++i) {            num[i]=lower_bound(hash+1,hash+hs+1,num[i])-hash;            segins(num[i],i,1,hs,1);        }        for(int i=0; i<m; ++i)            switch(op[i]) {            case 'Q':                printf("%d\n",hash[query(l[i]-1,r[i],k[i],1,hs,1)]);                break;            case 'C':                segdel(num[l[i]],l[i],1,hs,1);                num[l[i]]=lower_bound(hash+1,hash+hs+1,r[i])-hash;                segins(num[l[i]],l[i],1,hs,1);                break;            }    }}

  未完待续……

0 0