
1 18 Prior Add 1 Chat 1 Add 2 Chat 2 Top 2 Chat 3 Untop Chat 4 Choose 2 Chat 5 Rotate 2 Chat 4 Close 2 Add 3 Prior Chat 2 Close 1
Operation #1: empty. Operation #2: success. Operation #3: success. Operation #4: success. Operation #5: success. Operation #6: success. Operation #7: success. Operation #8: success. Operation #9: success. Operation #10: success. Operation #11: success. Operation #12: success. Operation #13: success. Operation #14: close 2 with 8. Operation #15: success. Operation #16: success. Operation #17: success. Operation #18: close 1 with 11. Bye 3: 2HintThis problem description does not relate to any real person in THU.
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=100100;
const int INF=0x3f3f3f3f;
//ll sum[maxn<<1];//子结点的和
map<int,int> mp;
int sz[maxn<<1],pre[maxn<<1],mv[maxn<<1],prr[maxn<<1],ch[maxn<<1][2];//sz记录子树规模,pre记录父结点,val存结点值。ch[k][0],ch[k][1]k的左右儿子。
int val[maxn<<1];
int mi,mo,root,s[maxn<<1];//mi回收内存。mo分配内存。root为根。s为内存池
void Treaval(int x)//Debug部分打出来非常清楚
{
if(x)
{
Treaval(ch[x][0]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d \n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
Treaval(ch[x][1]);
}
}
void Debug()
{
printf("root:%d\n",root);
Treaval(root);
}
void Newnode(int &rt,int v,int pr,int fa)
{
if(mi)//注意mi记录可用空间大小但里面没有空间所以要先减减。不然会出错
rt=s[--mi];
else
rt=mo++;
ch[rt][0]=ch[rt][1]=0;
//sum[r]=k;
pre[rt]=fa;
prr[rt]=pr;
sz[rt]=1;
mv[rt]=rt;
val[rt]=v;
}
void PushUp(int rt)
{
int ls,rs;
if(rt==0)
return;
ls=ch[rt][0],rs=ch[rt][1];
sz[rt]=sz[ls]+sz[rs]+1;
if(prr[mv[ls]]>prr[mv[rs]])
mv[rt]=mv[ls];
else
mv[rt]=mv[rs];
if(prr[rt]>prr[mv[rt]])
mv[rt]=rt;
//sum[rt]=sum[ls]+sum[rs]+val[rt];
}
void Init()//初始化很重要!
{
mi=root=0;
mo=1;
ch[0][0]=ch[0][1]=pre[0]=sz[0]=mv[0]=prr[0]=0;
val[0]=0;//建一个虚拟根节点。做标记用。pre==0说明就到根了
Newnode(root,0,0,0);//建真正的根和右儿子。必须加这两个虚拟结点。这样区间操作起来才方便
Newnode(ch[root][1],0,0,root);
PushUp(ch[root][1]);
PushUp(root);
}
void Rotate(int x,int w)//旋转。w为旋转方式。0为ZAG(x在右边)。1为ZIG(x在左边)。结点为左子树就右旋。右子树就左旋
{
int y=pre[x];
ch[y][!w]=ch[x][w];//把x往上转
pre[ch[x][w]]=y;
//PushDown(y)
//PushDown(x)
if(pre[y])
ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];
ch[x][w]=y;
pre[y]=x;
PushUp(y);
}
void Splay(int rt,int goal)//goal为目标父结点
{
int y,w;
while(pre[rt]!=goal)
{
if(pre[pre[rt]]==goal)
Rotate(rt,ch[pre[rt]][0]==rt);
else
{
y=pre[rt];
w=(ch[pre[y]][0]==y);
if(ch[y][w]==rt)
{
Rotate(rt,!w);
Rotate(rt,w);
}
else
{
Rotate(y,w);
Rotate(rt,w);
}
}
}
PushUp(rt);
if(goal==0)//旋转到根时更换根结点
root=rt;
}
int Get_kth(int rt,int k)//取第k个数的标号
{
int tp=sz[ch[rt][0]]+1;
if(tp==k)
return rt;
if(tp>k)
return Get_kth(ch[rt][0],k);
else
return Get_kth(ch[rt][1],k-tp);
}
int Insert(int pos,int v,int pr)//在pos位置插入一个数
{
Splay(Get_kth(root,pos),0);//因为前面有一个虚拟结点所以实际插的位置为pos+1
Splay(Get_kth(root,pos+1),root);
Newnode(ch[ch[root][1]][0],v,pr,ch[root][1]);
PushUp(ch[root][1]);
PushUp(root);
return ch[ch[root][1]][0];
}
void Delete(int rt)//删除结点
{
Splay(rt,0);//先把该点旋转到根
int pos=sz[ch[rt][0]];//获取它前面有多少个数
Splay(Get_kth(root,pos),0);
Splay(Get_kth(root,pos+2),root);
s[mi++]=rt;
ch[ch[root][1]][0]=0;
PushUp(ch[root][1]);
PushUp(root);
}
int main()
{
int n,op,i,t,pos,rt,top;
char cmd[15];
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
Init();
mp.clear();
top=-1;
for(i=1;i<=n;i++)
{
scanf("%s",cmd);
if(!strcmp(cmd,"Add"))
{
scanf("%d",&op);
if(mp.count(op))
printf("Operation #%d: same priority.\n",i);
else
{
pos=mp.size();
rt=Insert(pos+1,0,op);
mp[op]=rt;
printf("Operation #%d: success.\n",i);
}
}
else if(!strcmp(cmd,"Close"))
{
scanf("%d",&op);
if(mp.count(op))
{
printf("Operation #%d: close %d with %d.\n",i,op,val[mp[op]]);
Delete(mp[op]);
if(top==mp[op])
top=-1;
mp.erase(op);
}
else
printf("Operation #%d: invalid priority.\n",i);
}
else if(!strcmp(cmd,"Chat"))
{
scanf("%d",&op);
if(top!=-1)
{
val[top]+=op;
printf("Operation #%d: success.\n",i);
}
else if(mp.size())
{
pos=Get_kth(root,2);
val[pos]+=op;
printf("Operation #%d: success.\n",i);
}
else
printf("Operation #%d: empty.\n",i);
}
else if(!strcmp(cmd,"Rotate"))
{
scanf("%d",&op);
if(mp.size()>=op)
{
pos=Get_kth(root,op+1);
Delete(pos);
rt=Insert(1,val[pos],prr[pos]);
mp[prr[pos]]=rt;
if(pos==top)
top=rt;
printf("Operation #%d: success.\n",i);
}
else
printf("Operation #%d: out of range.\n",i);
}
else if(!strcmp(cmd,"Prior"))
{
if(mp.size())
{
pos=mv[root];
Delete(pos);
rt=Insert(1,val[pos],prr[pos]);
mp[prr[pos]]=rt;
if(top==pos)
top=rt;
printf("Operation #%d: success.\n",i);
}
else
printf("Operation #%d: empty.\n",i);
}
else if(!strcmp(cmd,"Choose"))
{
scanf("%d",&op);
if(mp.count(op))
{
pos=mp[op];
Delete(pos);
rt=Insert(1,val[pos],prr[pos]);
if(top==pos)
top=rt;
mp[op]=rt;
printf("Operation #%d: success.\n",i);
}
else
printf("Operation #%d: invalid priority.\n",i);
}
else if(!strcmp(cmd,"Top"))
{
scanf("%d",&op);
if(mp.count(op))
{
top=mp[op];
printf("Operation #%d: success.\n",i);
}
else
printf("Operation #%d: invalid priority.\n",i);
}
else if(!strcmp(cmd,"Untop"))
{
if(top!=-1)
{
top=-1;
printf("Operation #%d: success.\n",i);
}
else
printf("Operation #%d: no such person.\n",i);
}
}
if(top!=-1)
{
if(val[top])
printf("Bye %d: %d\n",prr[top],val[top]);
Delete(top);
}
while(sz[root]>2)
{
pos=Get_kth(root,2);
if(val[pos])
printf("Bye %d: %d\n",prr[pos],val[pos]);
Delete(pos);
}
}
return 0;
}
原文:http://blog.csdn.net/bossup/article/details/40408607