splay模板题,都快把我做忧郁了。
由于自己调两个坑点。
1.删除时及时updata
2.Kth 考虑k满足该点的条件即r->ch[1]->size+1<=k && r->ch[1]->size+r->num>=k
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 struct SplayNode 6 { 7 SplayNode *fa,*ch[2]; 8 SplayNode(); 9 int data,size,num; 10 int chr() {return this==fa->ch[1];} 11 void updata() { size=ch[0]->size+ch[1]->size+num;} 12 }*null; 13 SplayNode::SplayNode() {fa=ch[0]=ch[1]=null; num=1; size=0;} 14 int n,minn; 15 inline int read() {int ans=0; char c; while ((c=getchar())==‘ ‘ || c==‘\r‘ || c==‘\n‘); ans=c-‘0‘; while (isdigit(c=getchar())) ans=ans*10+c-‘0‘; return ans;} 16 namespace Splay 17 { 18 SplayNode *Root; 19 void MakeTree() 20 { 21 null=new SplayNode; 22 *null=SplayNode(); 23 Root=null; 24 } 25 void rotate(SplayNode *x) 26 { 27 SplayNode *r=x->fa; 28 if (x==null || r==null) return; 29 int t=x->chr(); 30 r->ch[t]=x->ch[t^1]; 31 r->ch[t]->fa=r; 32 if (r->fa==null) Root=x; 33 else r->fa->ch[r->chr()]=x; 34 x->fa=r->fa; 35 x->ch[t^1]=r; 36 r->fa=x; 37 r->updata(); 38 x->updata(); 39 } 40 void splay(SplayNode *x,SplayNode *y) 41 { 42 for (;x->fa!=y;rotate(x)) 43 if (x->fa->fa!=y) 44 if (x->chr()==x->fa->chr()) rotate(x->fa); 45 else rotate(x); 46 } 47 void insert(int v) 48 { 49 SplayNode *r=Root; 50 if (Root==null) 51 { 52 Root=new SplayNode; 53 Root->data=v; 54 Root->updata(); 55 return; 56 } 57 if (Root->data==v) 58 { 59 Root->num++; 60 Root->updata(); 61 return; 62 } 63 while (r->ch[r->data<v]!=null) 64 { 65 r=r->ch[r->data<v]; 66 if (r->data==v) 67 { 68 r->num++; 69 splay(r,null); 70 return; 71 } 72 } 73 r->ch[r->data<v]=new SplayNode; 74 r->ch[r->data<v]->data=v; 75 r->ch[r->data<v]->fa=r; 76 splay(r->ch[r->data<v],null); 77 } 78 void pre(SplayNode *x,int v,SplayNode *&ans) 79 { 80 if (x==null) return; 81 else if (x->data<v) 82 { 83 if (ans->data<x->data || ans==null) ans=x; 84 pre(x->ch[1],v,ans); 85 }else pre(x->ch[0],v,ans); 86 } 87 void suc(SplayNode *x,int v,SplayNode *&ans) 88 { 89 if (x==null) return; 90 else if (x->data>v) 91 { 92 if (ans->data>x->data || ans==null) ans=x; 93 suc(x->ch[0],v,ans); 94 }else suc(x->ch[1],v,ans); 95 } 96 void del(int v) 97 { 98 SplayNode *q=null; pre(Root,v,q); 99 SplayNode *p=null; suc(Root,v,p); 100 if (q==null && p==null) 101 { 102 if (Root->num==1) Root=null; 103 else Root->num--,Root->updata(); 104 return; 105 } 106 if (q==null) 107 { 108 splay(p,null); 109 if (p->ch[0]->num==1) p->ch[0]=null,p->updata(); 110 else p->ch[0]->num--,splay(p->ch[0],null); 111 return; 112 } 113 if (p==null) 114 { 115 splay(q,null); 116 if (q->ch[1]->num==1) p->ch[1]=null,p->updata(); 117 else p->ch[1]->num--,splay(p->ch[0],null); 118 return; 119 } 120 splay(q,null); 121 splay(p,q); 122 if (p->ch[0]->num==1) p->ch[0]=null,p->updata(); 123 else p->ch[0]->num--,splay(p->ch[0],null); 124 return; 125 } 126 SplayNode *Kth(int k) 127 { 128 SplayNode *r=Root; 129 while (r!=null) 130 { 131 if (k<=r->ch[1]->size) r=r->ch[1]; 132 else if (r->ch[1]->size+1<=k && r->ch[1]->size+r->num>=k) return r; 133 else 134 { 135 k-=r->ch[1]->size+r->num; 136 r=r->ch[0]; 137 } 138 } 139 return r; 140 } 141 SplayNode *find(int v) 142 { 143 SplayNode *r=Root; 144 while (r!=null) 145 { 146 if (r->data==v) 147 { 148 splay(r,null); 149 return r; 150 } 151 r=r->ch[r->data<v]; 152 } 153 return null; 154 } 155 } 156 int main() 157 { 158 //freopen("1503.out","w",stdout); 159 int ans=0,dell=0,ans1=0; 160 Splay::MakeTree(); 161 n=read(); minn=read(); 162 while (n--) 163 { 164 char s[6]; 165 int x; 166 scanf("%s",s); x=read(); 167 if (s[0]==‘I‘) if (x>=minn) Splay::insert(x-dell),ans++; 168 if (s[0]==‘A‘) dell+=x; 169 if (s[0]==‘S‘) 170 { 171 dell-=x; 172 Splay::insert(minn-dell); 173 SplayNode *r=Splay::find(minn-dell); 174 // Splay::splay(r,null); 175 if (r->ch[0]!=null) ans1+=r->ch[0]->size,ans-=r->ch[0]->size; 176 while (r->ch[0]!=null) 177 { 178 Splay::del(r->ch[0]->data); 179 Splay::splay(r,null); 180 } 181 Splay::del(minn-dell); 182 } 183 if (s[0]==‘F‘) 184 if (x>ans) puts("-1"); 185 else 186 printf("%d\n",Splay::Kth(x)->data+dell); 187 } 188 printf("%d\n",ans1); 189 return 0; 190 }
Description
OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?
Input
Output
输出文件的行数为F命令的条数加一。对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,如果k大于目前员工的数目,则输出-1。输出文件的最后一行包含一个整数,为离开公司的员工的总数。
Sample Input
9 10
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2
Sample Output
10
20
-1
2
HINT
I命令的条数不超过100000 A命令和S命令的总条数不超过100 F命令的条数不超过100000 每次工资调整的调整量不超过1000 新员工的工资不超过100000