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
- BZOJ1503 NOI2004 郁闷的出纳员 题解&代码
- [题解]bzoj1503(NOI2004)郁闷的出纳员
- [bzoj1503][NOI2004]郁闷的出纳员
- BZOJ1503【NOI2004】郁闷的出纳员
- [BZOJ1503][NOI2004]郁闷的出纳员
- bzoj1503【NOI2004】郁闷的出纳员
- [BZOJ1503] [NOI2004]郁闷的出纳员
- 【bzoj1503】[NOI2004]郁闷的出纳员
- 【BZOJ1503】[NOI2004]郁闷的出纳员
- bzoj1503: [NOI2004]郁闷的出纳员
- BZOJ1503: [NOI2004]郁闷的出纳员
- 【bzoj1503】[NOI2004]郁闷的出纳员
- 【bzoj1503】 [NOI2004]郁闷的出纳员
- bzoj1503: [NOI2004]郁闷的出纳员
- BZOJ1503: [NOI2004]郁闷的出纳员
- 【平衡树】BZOJ1503(NOI2004)[郁闷的出纳员]题解
- bzoj1503: [NOI2004]郁闷的出纳员 SBT
- [BZOJ1503]NOI2004 郁闷的出纳员|splay
- C++ Queues(队列)、Priority Queues(优先队列)
- POJ 1703 Find them, Catch them(并查集)
- 【笔记】jQuery中on()与delegate()方法给动态添加元素绑定事件
- OpenStack高可用核心架构分析
- c strtok()
- BZOJ1503 NOI2004 郁闷的出纳员 题解&代码
- MAC如何获取IPHONE中的crash log
- [CSS3 Practice] Simulate MacBook Dock
- 【概率】poj 2096:Collecting Bugs
- 过山车
- postgresql 优化之--不会使用索引
- mysql 性能小记
- angularjs指令中的compile与link函数详解
- Trac搭建