T1 郁闷的出纳员
一个数据结构,支持单点插入、删除几个不一定连续的点、查询k值操作
初做:2017.2.18 time:1268ms memory:3MB
http://www.cnblogs.com/TheRoadToTheGold/p/6412790.html
现在:2017.3.28 time:570ms memory:3MB
初做时直接套模板,删除分5种情况,
本题实际只需3种情况
这一次的查询用递归写的
int query(int now,int k)
{
int tmp=0;
if(ch[now][0]) tmp=sum[ch[now][0]];
if(k<=tmp) return query(ch[now][0],k);
if(tmp+cnt[now]>=k) return key[now];
return query(ch[now][1],k-tmp-cnt[now]);
}
5行开始写的时候每一行都有错误
第二行:tmp=左子树节点个数,遗漏了判断是否有左子树
第三行:当k<=左子树节点个数,漏了等于号
第四行:左子树节点个数+根节点个数(cnt[]数组)>=k,cnt[]和sum[]混了,>写的<
第五行:cnt和sum混了
再就是splay写丑了
贴个精简的:
inline void splay(int x) { for(int fa;fa=f[x];rotate(x)) if(f[fa]) rotate(getson(x)==getson(fa) ? fa:x); root=x; update(x); }
一定要注意update时节点是否有左右孩子
rotate里出现了一个错误:
if(z) ch[z][ch[z][1]==y]=x;
fa[x]=z;这一句是不在if(z)里的
#include<cstdio> #define N 100001 using namespace std; int n,limit,gather,root,tot,leave; int sum[N],ch[N][2],fa[N],key[N],cnt[N]; void newroot(int x) { sum[++tot]=cnt[tot]=1; key[tot]=x; root=tot; } void newnode(int f,int x) { sum[++tot]=cnt[tot]=1; key[tot]=x; fa[tot]=f; ch[f][x>key[f]]=tot; } void update(int x) { sum[x]=cnt[x]; if(ch[x][0]) sum[x]+=sum[ch[x][0]]; if(ch[x][1]) sum[x]+=sum[ch[x][1]]; } void rotate(int x,int kind) { int y=fa[x],z=fa[y]; ch[y][!kind]=ch[x][kind]; fa[ch[y][!kind]]=y; ch[x][kind]=y;fa[y]=x; fa[x]=z; if(z) ch[z][ch[z][1]==y]=x; update(y); } void splay(int x) { while(fa[x]) { int y=fa[x],kind=ch[y][1]==x; if(!fa[y]) rotate(x,!kind); else { int z=ch[fa[y]][1]==y; if(z==kind) { rotate(y,!kind); rotate(x,!kind); } else { rotate(x,!kind); rotate(x,kind); } } } update(x); root=x; } void insert(int x) { if(!root) { newroot(x); return; } int now=root; while(ch[now][x>key[now]]) { if(key[now]==x) { cnt[now]++; update(now); splay(now); return; } now=ch[now][x>key[now]]; } if(key[now]==x) { cnt[now]++; update(now); splay(now); return; } newnode(now,x); update(now); splay(tot); } void cut_lch() { int tmp=ch[root][0]; if(tmp) leave+=sum[tmp]; fa[tmp]=0; ch[root][0]=0; update(root); } void cut() { if(cnt[root]>1) { cnt[root]--; update(root); return; } if(!ch[root][1]) { root=0; gather=0; return; } int tmp=ch[root][1]; fa[tmp]=0; ch[root][1]=0; root=tmp; } int query(int now,int k) { int tmp=0; if(ch[now][0]) tmp=sum[ch[now][0]]; if(k<=tmp) return query(ch[now][0],k); if(tmp+cnt[now]>=k) return key[now]; return query(ch[now][1],k-tmp-cnt[now]); } int main() { freopen("cashier.in","r",stdin); freopen("cashier.out","w",stdout); scanf("%d%d",&n,&limit); char ch[1];int x; while(n--) { scanf("%s%d",ch,&x); switch(ch[0]) { case 'I': if(x<limit) continue; insert(x-gather); break; case 'A': gather+=x; break; case 'S': gather-=x; insert(limit-gather); cut_lch(); cut(); break; case 'F': if(x>sum[root]) printf("-1\n"); else printf("%d\n",query(root,sum[root]-x+1)+gather); } } printf("%d",leave); }