BZOJ1503 NOI2004 郁闷的出纳员 题解&代码

来源:互联网 发布:淘宝怎么买东西 编辑:程序博客网 时间:2024/06/09 17:35

题意太傻不多解释= =就是维护一个档案队列,按节点val建树

思路:
从query操作(命令F)可以看出,这棵树的顺序核心在于value而不是一般的维护队列,这样的话相同value的节点显而易见地应该放在一起,我们除了s[]记录子树大小之外,额外增加一个z[]记录节点大小(对于x节点来说每有一个与其value重复的z[x]++),注意z[]不需要维护。
然后就是喜闻乐见的标记了,这道题算是比较良心= =只需要维护两个标记
add[]对当前子树进行范围修改的lazy标记
val[]单点val,需要在维护add[]的时候一起维护

然后= =就是想起来就有种自己傻的反思时间
1、Splay居然又写错了!循环时没有同步更新y和z!调了半个小时才输出出来错在这!
2、最初思路不够清晰就开始写,结果用值查找节点的时候因为想要在多个函数中用到getval这个函数两面都想满足= =结果两边都求错了【23333
3、最开始没有想到节点值相同时该怎么维护,结果只好新建节点维护成一个队列= =结局可想而知
4、查找第k大的时候想错= =如果当前节点val大于目标val直接向左走了,其实应该记录一下路径中最接近目标val的节点
5、query的时候顺序反了= =结果自己怎么看都没错,输出就是有问题…在更新了x之后想要得到关于原x的信息是自己活在梦里

于是…用了一个半小时写完了代码用了四个半小时调= =下一道Splay再这样就药丸了

#include<iostream>#include<stdio.h>#define lson ch[x][0]#define rson ch[x][1]using namespace std;const int maxn=100005;int n,m,k,ans,tot,root;int ch[maxn][2],fa[maxn],add[maxn],val[maxn],s[maxn],z[maxn];char str[5];void link(int x,int y,int d){    if(y)ch[y][d]=x;    if(x)fa[x]=y;    //cout<<"link "<<x<<' '<<fa[x]<<' '<<d<<endl;}int ischild(int x){    return ch[fa[x]][1]==x;}void maintain(int x){    if(x)s[x]=s[lson]+s[rson]+z[x];}void pushdown(int x){    if(!add[x])return;    if(lson)add[lson]+=add[x],val[lson]+=add[x];    if(rson)add[rson]+=add[x],val[rson]+=add[x];    add[x]=0;}void rotate(int x){    int d=ischild(x);    int y=fa[x],z=fa[y];    if(y==root)root=x;    link(x,z,ischild(y));    link(ch[x][!d],y,d);    link(y,x,!d);    maintain(y);}void Splay(int x,int goal=0){    int y=fa[x],z=fa[y];    while(y!=goal)    {        pushdown(z);        pushdown(y);        pushdown(x);        if(z==goal)        {            rotate(x);            break;        }        if(ischild(x) ^ ischild(y))rotate(x);        else rotate(y);        rotate(x);        y=fa[x],z=fa[y];//false    }    maintain(x);}int getnext(int x){    x=ch[x][1];    while(ch[x][0])x=ch[x][0];    return x;}int getval(int k){    int x=root;    while(x)    {        pushdown(x);        if(val[x]==k)return x;//false        if(ch[x][val[x]<k])x=ch[x][val[x]<k];        else return x;    }    return x;}int newnode(int v){    int t=++tot;    s[t]=z[t]=1;    val[t]=v;    return t;}void addtree(int k){    if(!root)    {        root=newnode(k);        return;    }    int x=getval(k);    if(val[x]==k)z[x]++;    else link(newnode(k),x,val[x]<k);    Splay(x);}void increase(int k){    if(!root)return;    add[root]+=k;    val[root]+=k;}void decrease(int k){    if(!root)return;    add[root]-=k;    val[root]-=k;    int x=root,pre=0;    while(x)    {        pushdown(x);        if(val[x]==m)break;//false        if(val[x]<m)x=ch[x][1];        else        {            pre=x;            x=ch[x][0];        }    }    if(!x)x=pre;    if(x)Splay(x);    if(!x)ans+=s[root],root=0;    else ans+=s[ch[x][0]],ch[x][0]=0;    maintain(x);}int query(int k){    int x=root;    int t;    while(x)    {        pushdown(x);        t=s[ch[x][1]];        if(t>=k)x=ch[x][1];        else            if(t+z[x]>=k)return val[x];            else k-=t+z[x],x=ch[x][0];//else x=ch[x][0],k-=t+z[x];false    }    if(x)return val[x];    else return -1;}int que(int x,int k){    if(!x)return -1;    pushdown(x);    if(s[ch[x][1]]>=k)return que(ch[x][1],k);    if(s[ch[x][1]]+z[x]>=k)return val[x];    return que(ch[x][0],k-s[ch[x][1]]-z[x]);}int main(void){    //freopen("cashier2.in","r",stdin);    //freopen("cashier.ans","w",stdout);    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        scanf("%s%d",str,&k);        //printf("%c %d\n",str[0],k);        if(str[0]=='I')            if(k>=m)addtree(k);        if(str[0]=='A')increase(k);        if(str[0]=='S')decrease(k);        if(str[0]=='F')printf("%d\n",query(k));    }    printf("%d\n",ans);    return 0;}
0 0
原创粉丝点击