bzoj1503: [NOI2004]郁闷的出纳员(伸展树)

来源:互联网 发布:linux管道命令是啥 编辑:程序博客网 时间:2024/06/10 04:22

题目传送门
基本也算入门题了。

解法:
就伸展树维护一下然后加个暴力吧。

代码实现:

#include<cstdio>#include<cstring>#include<cmath>using namespace std;int root;struct node {    int d,n,c,f,son[2];} tr[110000];int len;void update(int x) {    int lc=tr[x].son[0],rc=tr[x].son[1];    tr[x].c=tr[lc].c+tr[rc].c+tr[x].n;}void add(int d,int f) {    len++;    tr[len].d=d;tr[len].n=1;tr[len].c=1;tr[len].f=f;    if(d<tr[f].d)        tr[f].son[0]=len;    else         tr[f].son[1]=len;    tr[len].son[0]=tr[len].son[1]=0;}void rotate(int x,int w) {    int f=tr[x].f,ff=tr[f].f;    int R,r;    R=f;    r=tr[x].son[w];    tr[R].son[1-w]=r;    if(r!=0)        tr[r].f=R;    R=ff;r=x;    if(tr[R].son[0]==f)        tr[R].son[0]=r;    else         tr[R].son[1]=r;    tr[r].f=R;    R=x;r=f;    tr[R].son[w]=r;    tr[r].f=R;    update(f);    update(x);}void splay(int x,int rt) {    while(tr[x].f!=rt) {        int f=tr[x].f,ff=tr[f].f;        if(ff==rt) {            if(tr[f].son[0]==x)                rotate(x,1);            else                 rotate(x,0);        }         else {            if(tr[ff].son[0]==f&&tr[f].son[0]==x) {                rotate(f,1);rotate(x,1);            }             else if(tr[ff].son[1]==f&&tr[f].son[1]==x) {                rotate(f,0);rotate(x,0);            }             else if(tr[ff].son[0]==f&&tr[f].son[1]==x) {                rotate(x,0);rotate(x,1);            }             else if(tr[ff].son[1]==f&&tr[f].son[0]==x) {                rotate(x,1);rotate(x,0);            }        }    }    if(rt==0)root=x;}int findip(int d) {    int x=root;    while(tr[x].d!=d) {        if(d<tr[x].d) {            if(tr[x].son[0]==0)                break;            x=tr[x].son[0];        }         else {            if(tr[x].son[1]==0)                break;            x=tr[x].son[1];        }    }    return x;}void ins(int d) {    if(root==0) {        add(d,0);        root=len;        return ;    }    int x=findip(d);    if(tr[x].d==d) {        tr[x].n++;        update(x);        splay(x,0);    }     else {        add(d,x);        update(x);        splay(len,0);    }}int ans;void del(int x) {    splay(x,0);    ans+=tr[x].n;    if(tr[x].son[0]==0&&tr[x].son[1]==0) {        root=0;        len=0;    }     else if(tr[x].son[0]==0&&tr[x].son[1]!=0) {        root=tr[x].son[1];        tr[root].f=0;    }     else if(tr[x].son[0]!=0&&tr[x].son[1]==0) {        root=tr[x].son[0];        tr[root].f=0;    }     else {        int p=tr[x].son[0];        while(tr[p].son[1]!=0)p=tr[p].son[1];        splay(p,x);        int r=tr[x].son[1],R=p;        tr[R].son[1]=r;        tr[r].f=R;        root=R;        tr[root].f=0;        update(R);    }}void findpaiming(int d) {    int x=findip(d);    splay(x,0);    printf("%d\n",tr[tr[x].son[0]].c+1);}void findshuzhi(int k) {    if(tr[root].c<k) {        printf("-1\n");        return ;    }    int x=root;    while(1) {        int lc=tr[x].son[0],rc=tr[x].son[1];        if(k<=tr[rc].c)            x=rc;        else if(k>tr[rc].c+tr[x].n) {            k-=tr[rc].c+tr[x].n;            x=lc;        }         else             break;    }    splay(x,0);    printf("%d\n",tr[x].d);}void findqianqu(int d) {    int x=findip(d);    splay(x,0);    if(d<=tr[x].d) {        x=tr[x].son[0];        while(tr[x].son[1]!=0)            x=tr[x].son[1];    }    printf("%d\n",tr[x].d);}void findhouji(int d) {    int x=findip(d);    splay(x,0);    if(tr[x].d<=d) {        x=tr[x].son[1];        while(tr[x].son[0]!=0)            x=tr[x].son[0];    }    printf("%d\n",tr[x].d);}int mmin,shan[110000],slen;void zhengjia(int x,int k) {    tr[x].d+=k;    if(tr[x].son[0]!=0)        zhengjia(tr[x].son[0],k);    if(tr[x].son[1]!=0)        zhengjia(tr[x].son[1],k);}void jianshao(int x,int k) {    tr[x].d-=k;    if(tr[x].d<mmin)        shan[++slen]=x;    if(tr[x].son[0]!=0)        jianshao(tr[x].son[0],k);    if(tr[x].son[1]!=0)        jianshao(tr[x].son[1],k);}int shanchu() {    for(int i=1; i<=slen; i++)        del(shan[i]);}int main() {    int n,x;    char ss[5];    scanf("%d%d",&n,&mmin);    ans=0;    for(int i=1; i<=n; i++) {        scanf("%s%d",ss+1,&x);        if(ss[1]=='I') {            if(x>=mmin)ins(x);        }         else if(ss[1]=='F')            findshuzhi(x);        else if(ss[1]=='A')            zhengjia(root,x);        else if(ss[1]=='S') {            slen=0;            jianshao(root,x);            shanchu();        }    }    printf("%d\n",ans);    return 0;}
原创粉丝点击