CODEVS 1286(伸展树)

来源:互联网 发布:沃尔玛数据流程图 编辑:程序博客网 时间:2024/06/12 06:34

题目链接:http://codevs.cn/problem/1286/
题解:伸展树,一定要记住,任何被操作过的节点都要旋转到根,插入节点后要把该节点旋转到根,查找节点后也要把它旋转到根,删除节点也要先旋转到根再删除,如果不旋转到根,妥妥的超时。

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define N 100010int c[N][2],fa[N],v[N],num[N],sum[N];int n,m,cnt,rt;void pushup(int k){    sum[k]=sum[c[k][0]]+sum[c[k][1]]+num[k];}void rotate(int x,int &k){    int y=fa[x],z=fa[y],l,r;    if(c[y][0]==x) l=0;else l=1;r=l^1;    if(y==k) k=x;    else if(c[z][0]==y) c[z][0]=x;else c[z][1]=x;    fa[x]=z;fa[y]=x;fa[c[x][r]]=y;    c[y][l]=c[x][r];c[x][r]=y;    pushup(y);pushup(x);}void splay(int x,int &k){    while(x!=k)    {        int y=fa[x],z=fa[y];        if(y!=k)        {            if(c[z][0]==y^c[y][0]==x) rotate(x,k);            else rotate(y,k);        }        else rotate(x,k);    }}void ins(int val,int &k,int last){    if(k==0)    {        k=++cnt;v[k]=val;fa[k]=last;num[k]=sum[k]=1;        splay(k,rt);    }    else if(v[k]==val)    {        ++num[k];++sum[k];splay(k,rt);    }    else if(val<=v[k]) ++sum[k],ins(val,c[k][0],k);    else ++sum[k],ins(val,c[k][1],k);}int find(int k,int val){    if(k==0) return 0;    else if(v[k]+val>=m) return find(c[k][0],val);    else    {        int t=find(c[k][1],val);        if(t==0) t=k;        return t;    }}void del(int val){    int x=find(rt,val);    if(x==0) return;    splay(x,rt);    rt=c[x][1];fa[rt]=0;}int find_k(int k,int rank){    int l=c[k][0],r=c[k][1];    if(rank<=sum[r]) return find_k(r,rank);    else if(sum[r]+num[k]<rank) return find_k(l,rank-sum[r]-num[k]);    else    {        splay(k,rt);return v[k];    }}int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9')ch=getchar();    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x;}int main(){    n=read();m=read();    int z=0,k,tot=0;    char ch;    for(int i=1;i<=n;++i)    {        for(ch=getchar();ch<'A'||'Z'<ch;ch=getchar());        k=read();        switch(ch)        {            case 'I':if(k>=m) ++tot,ins(k-z,rt,0);break;            case 'A':z+=k;break;            case 'S':z-=k;del(z);break;            case 'F':                if(k>sum[rt]) printf("-1\n");                else printf("%d\n",find_k(rt,k)+z);                break;        }    }    printf("%d\n",tot-sum[rt]);    return 0;}
原创粉丝点击