Splay
AC tyvj1728 普通平衡树
1 #include <cstdio>
2 #include <iostream>
3 #include <fstream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <cmath>
8 #include <algorithm>
9
10 typedef long long int ll;
11 typedef double db;
12
13 using namespace std;
14
15 struct SplayTree
16 {
17 struct node
18 {
19 int v;
20 int tot;
21 node*s[2];
22 node*f;
23
24 void update()
25 {
26 tot=s[0]->tot + s[1]->tot +1;
27 }
28 };
29 node*pool;
30 node*nt;
31 node*nil;
32 node*newnode(node*f,int v)
33 {
34 nt->v=v;
35 nt->tot=1;
36 nt->s[0]=nt->s[1]=nil;
37 nt->f=f;
38 return nt++;
39 }
40
41 node*root;
42
43 SplayTree(int size)
44 {
45 pool=new node[size+1];
46 nt=pool;
47 nil=newnode(NULL,-1);
48 nil->tot=0;
49 nil->f=nil->s[0]=nil->s[1]=nil;
50 root=nil;
51 }
52
53 //===============================================
54
55 void update(node*x)
56 {
57 x->tot= x->s[0]->tot + x->s[1]->tot +1;
58 }
59
60 void rot(node*x)
61 {
62 if(x==nil) return ;
63
64 node*y=x->f;
65 int k=(x==y->s[0]);
66
67 y->s[k^1]=x->s[k];
68 if(x->s[k]!=nil) x->s[k]->f=y;
69
70 x->f=y->f;
71 if(y==y->f->s[0]) y->f->s[0]=x;
72 else if(y==y->f->s[1]) y->f->s[1]=x;
73
74 y->f=x;
75 x->s[k]=y;
76
77 y->update();
78 }
79
80 void splay(node*x) { splay(x,nil); }
81 void splay(node*x,node*t)
82 {
83 if(x==nil) return ;
84 while(x->f!=t)
85 {
86 node*y=x->f;
87 if(y->f!=t)
88 if((x==y->s[0])^(y==y->f->s[0]))
89 rot(x); else rot(y);
90 rot(x);
91 }
92 x->update();
93
94 if(t==nil) root=x;
95 }
96
97 //=============================================
98
99 void Insert(int v)
100 {
101 if(root==nil)
102 {
103 root=newnode(nil,v);
104 return ;
105 }
106
107 node*x=root;
108 node*y=x;
109 while(x!=nil)
110 {
111 y=x;
112 if(v<x->v) x=x->s[0];
113 else x=x->s[1];
114 }
115
116 int k=!(v<y->v);
117 y->s[k]=newnode(y,v);
118 splay(y->s[k]);
119 }
120
121
122 node*Find(int v)
123 {
124 node*x=root;
125 node*y=x;
126 node*r=nil;
127 while(x!=nil)
128 {
129 y=x;
130 if(x->v==v) r=x;
131 if(v<=x->v) x=x->s[0];
132 else x=x->s[1];
133 }
134 splay(y);
135 return r;
136 }
137
138 node* FindRank(int k)
139 {
140 node*x=root;
141 node*y=x;
142 while(x!=nil)
143 {
144 y=x;
145 if(k==x->s[0]->tot+1) break;
146
147 if(k<x->s[0]->tot+1)
148 x=x->s[0];
149 else
150 {
151 k-=x->s[0]->tot+1;
152 x=x->s[1];
153 }
154 }
155 splay(y);
156 return x;
157 }
158
159 int GetRank(node*x)
160 {
161 splay(x);
162 return x->s[0]->tot+1;
163 }
164
165 int GetRevRank(node*x)
166 {
167 splay(x);
168 return x->s[1]->tot+1;
169 }
170
171 node*Delete(node*x)
172 {
173 int k=GetRank(x);
174 node*L=FindRank(k-1);
175 node*R=FindRank(k+1);
176
177 splay(L);
178 splay(R,L);
179
180 if(L==nil && R==nil) root=nil;
181 else if(R==nil) L->s[1]=nil;
182 else R->s[0]=nil;
183
184 if(R!=nil) update(R);
185 if(L!=nil) update(L);
186
187 return x;
188 }
189
190 node*prefix(int v)
191 {
192 node*x=root;
193 node*y=x;
194 node*r=nil;
195 while(x!=nil)
196 {
197 y=x;
198 if(x->v<v) r=x;
199 if(v<=x->v) x=x->s[0];
200 else x=x->s[1];
201 }
202 splay(y);
203 return r;
204 }
205
206 node*suffix(int v)
207 {
208 node*x=root;
209 node*y=x;
210 node*r=nil;
211 while(x!=nil)
212 {
213 y=x;
214 if(x->v>v) r=x;
215 if(v<x->v) x=x->s[0];
216 else x=x->s[1];
217 }
218 splay(y);
219 return r;
220 }
221
222
223
224
225 //===========================================
226 void output() { output(root); printf("%s\n",root==nil ? "empty tree!" : ""); }
227 void output(node*x)
228 {
229 if(x==nil)return ;
230 output(x->s[0]);
231 printf("%d ",x->v);
232 output(x->s[1]);
233 }
234
235 void test() { test(root); printf("%s\n",root==nil ? "empty tree!" : ""); }
236 void test(node*x)
237 {
238 if(x==nil)return ;
239 test(x->s[0]);
240 printf("%p [ v:%d f:%p L:%p R:%p tot:%d ] \n",x,x->v,x->f,x->s[0],x->s[1],x->tot);
241 test(x->s[1]);
242 }
243
244 };
245
246
247 int n;
248
249 int main()
250 {
251 scanf("%d",&n);
252 SplayTree st(n);
253
254 for(int i=0;i<n;i++)
255 {
256 int c;
257 scanf("%d",&c);
258 switch(c)
259 {
260 case 1: //Insert
261 scanf("%d",&c);
262 st.Insert(c);
263 break;
264 case 2: //Delete
265 scanf("%d",&c);
266 st.Delete(st.Find(c));
267 break;
268 case 3: //Rank
269 scanf("%d",&c);
270 printf("%d\n",st.GetRank(st.Find(c)));
271 break;
272 case 4: //FindRank
273 scanf("%d",&c);
274 printf("%d\n",st.FindRank(c)->v);
275 break;
276 case 5: //prefix
277 scanf("%d",&c);
278 printf("%d\n",st.prefix(c)->v);
279 break;
280 case 6: //suffix
281 scanf("%d",&c);
282 printf("%d\n",st.suffix(c)->v);
283 break;
284 case 7: //test
285 st.test();
286 break;
287 default: break;
288 }
289 }
290
291 return 0;
292 }
2015年2月19日更新:
我现在才发现我写的双旋一直都是错的!!!!!
记住如果是折线就两次rot(x),直线才是先y后x! if((x==y->s[0])^(y==y->f->s[0])) rot(x); else rot(y);
要点1.别忘了有事没事splay一下保证复杂度.....
要点2.各种if的顺序别搞混了!有些if是不能合并的.
要点3.记住splay前的特判.如果要单独使用rotate就给rotate也加特判.
要点4.不要有事没事就更改某些子树的位置!比如在delete的时候,提x作根,然后找到右子树最左边的节点后,合并左右两颗子树,这是会超时的!
AC BZOJ 2733
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 #include <bitset>
18
19 typedef unsigned int uint;
20 typedef long long int ll;
21 typedef unsigned long long int ull;
22 typedef double db;
23
24 using namespace std;
25
26 inline int getint()
27 {
28 int res=0;
29 char c=getchar();
30 bool mi=false;
31 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
32 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
33 return mi ? -res : res;
34 }
35 inline ll getll()
36 {
37 ll res=0;
38 char c=getchar();
39 bool mi=false;
40 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
41 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
42 return mi ? -res : res;
43 }
44
45 //==============================================================================
46 //==============================================================================
47 //==============================================================================
48 //==============================================================================
49
50 struct node*nil;
51 struct node
52 {
53 int v;
54 int tot;
55 node*s[2],*f;
56 int code;
57 void update(){ tot = s[0]->tot + s[1]->tot +1; }
58
59 };
60 node*nt;
61 int ncnt=10000;
62 node*newnode(node*f,int v,int c)
63 {
64 if(ncnt==10000) { ncnt=0; nt=new node[10000]; }
65 nt->f=f;
66 nt->s[0]=nt->s[1]=nil;
67 nt->tot=1;
68 nt->v=v;
69 nt->code=c;
70 ncnt++;
71 return nt++;
72 }
73
74 struct SplayTree
75 {
76 node*root;
77
78 SplayTree(){ root=nil; }
79
80 void rot(node*x)
81 {
82 node*y=x->f;
83 if(y==nil) return ;
84 int k=(x==y->s[0]);
85
86 y->s[!k]=x->s[k];
87 if(x->s[k]!=nil) x->s[k]->f=y;
88
89 x->f=y->f;
90 if(y==y->f->s[0]) y->f->s[0]=x;
91 else if(y==y->f->s[1]) y->f->s[1]=x;
92
93 y->f=x;
94 x->s[k]=y;
95
96 y->update();
97 }
98
99 void splay(node*x,node*t=nil)
100 {
101 while(x->f!=t)
102 {
103 node*y=x->f;
104 if(y->f!=t)
105 if((x==y->s[0])^(y==y->f->s[0]))
106 rot(x); else rot(y);
107 rot(x);
108 }
109 x->update();
110 if(t==nil) root=x;
111 }
112
113 void Insert(int v,int c)
114 { root=newnode(nil,v,c); }
115
116 void Insert(node*t)
117 {
118 if(root==nil)
119 { root=t; t->s[0]=t->s[1]=t->f=nil; t->tot=1; return ; }
120
121 node*x=root;
122 node*y=nil;
123 while(x!=nil)
124 y=x,x=x->s[t->v>=x->v];
125
126 int k=(t->v>=y->v);
127
128 t->s[0]=t->s[1]=nil; t->tot=1;
129 y->s[k]=t; t->f=y;
130
131 splay(t);
132 }
133
134 node*FindRank(int k)
135 {
136 if(k>root->tot || k<=0) return nil;
137 node*x=root;
138 node*y=nil;
139 while(x!=nil)
140 {
141 y=x;
142 if(k==x->s[0]->tot+1) break;
143 if(k>x->s[0]->tot+1)
144 {
145 k-=x->s[0]->tot+1;
146 x=x->s[1];
147 }
148 else
149 x=x->s[0];
150 }
151 splay(y);
152 return y;
153 }
154 };
155
156 node*ary[105000]; int ac,ah;
157 void Merge(SplayTree*&A,SplayTree*&B)
158 {
159 if(A->root==B->root) return ;
160 if(A->root->tot>B->root->tot) swap(A,B);
161 //descrete nodes of A and insert to B.
162 ah=ac=0;
163 ary[ac++]=A->root;
164 while(ah!=ac)
165 {
166 node*x=ary[ah];
167 if(x->s[0]!=nil) ary[ac++]=x->s[0];
168 if(x->s[1]!=nil) ary[ac++]=x->s[1];
169 B->Insert(x);
170 ah++;
171 }
172 A=B;
173 }
174
175 SplayTree**T;
176
177 int n,m,q;
178
179 int main()
180 {
181 nil=new node;
182 nil->f=nil->s[0]=nil->s[1]=nil;
183 nil->tot=0;
184 nil->code=nil->v=-2;
185
186 n=getint();
187 m=getint();
188
189 T=new SplayTree*[n];
190 for(int i=0;i<n;i++)
191 {
192 T[i]=new SplayTree;
193 T[i]->Insert(getint(),i);
194 }
195
196 for(int i=0;i<m;i++)
197 {
198 int a=getint()-1;
199 int b=getint()-1;
200 if(T[a]!=T[b]) Merge(T[a],T[b]);
201 }
202
203 q=getint();
204 for(int i=0;i<q;i++)
205 {
206 char c=getchar();
207 while(c!='B' && c!='Q') c=getchar();
208 int a=getint()-1;
209 int b=getint()-1;
210 if(c=='B')
211 {
212 if(T[a]!=T[b]) Merge(T[a],T[b]);
213 }
214 else if(c=='Q')
215 {
216 if(a<0 || a>=n) printf("%d\n",-1);
217 else
218 printf("%d\n",T[a]->FindRank(b+1)->code+1);
219 }
220 }
221
222 return 0;
223 }
启发式合并两棵SplayTree.
代码好长....
速度好慢.....
o(╯□╰)o......
Treap
虽然说蛮好玩的.....
速度快得不行....
但是感觉代码复杂度跟splay一样啊.....
AC BZOJ3224 普通平衡树
排序Treap.
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21
22 using namespace std;
23
24 inline int getint()
25 {
26 int res=0;
27 char c=getchar();
28 bool mi=false;
29 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
30 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
31 return mi ? -res : res;
32 }
33 inline ll getll()
34 {
35 ll res=0;
36 char c=getchar();
37 bool mi=false;
38 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
39 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
40 return mi ? -res : res;
41 }
42
43 db eps=1e-80;
44 inline bool feq(db a,db b)
45 { return fabs(a-b)<eps; }
46
47 template<typename Type>
48 inline Type avg(const Type a,const Type b)
49 { return a+((b-a)/2); }
50
51 //===================================================================
52 //===================================================================
53 //===================================================================
54 //===================================================================
55
56 int INF=(1<<30)-1;
57
58 int getrand()
59 { return rand()+32768*rand(); }
60
61 int t[105000];
62 int tot[105000];
63 int hp[105000];
64 int s[105000][2];
65 int f[105000];
66 int ntot=1;
67
68 int n;
69
70 void update(int x)
71 { if(x) tot[x] = tot[s[x][0]] + tot[s[x][1]] +1; }
72
73 int root=0;
74 void rot(int x)
75 {
76 int y=f[x];
77 int k=(x==s[y][0]);
78 s[y][!k]=s[x][k];
79 if(s[x][k]) f[s[x][k]]=y;
80 f[x]=f[y];
81 if(y==s[f[y]][0]) s[f[y]][0]=x;
82 else if(y==s[f[y]][1]) s[f[y]][1]=x;
83 f[y]=x;
84 s[x][k]=y;
85 update(y);
86 update(x);
87 if(!f[x]) root=x;
88 }
89
90 int lift(int x)
91 { while(f[x] && hp[x]<hp[f[x]]) rot(x);}
92
93 void Insert(int v)
94 {
95 if(!root)
96 { t[ntot]=v; tot[ntot]=1; root=ntot++; return ; }
97
98 int x=root;
99 int k=-1;
100 while(true)
101 {
102 tot[x]++;
103 if(v>t[x])
104 {
105 if(!s[x][1]) { k=1; break; }
106 x=s[x][1];
107 }
108 else
109 {
110 if(!s[x][0]) { k=0; break; }
111 x=s[x][0];
112 }
113 }
114
115 f[ntot]=x;
116 tot[ntot]=1;
117 hp[ntot]=getrand();
118 t[ntot]=v;
119 s[x][k]=ntot++;
120 lift(s[x][k]);
121 }
122
123 int FindRank(int k)
124 {
125 int x=root;
126 int y=0;
127 while(x)
128 {
129 y=x;
130 if(k==tot[s[x][0]]+1) break;
131 if(k<=tot[s[x][0]])
132 x=s[x][0];
133 else
134 {
135 k-=tot[s[x][0]]+1;
136 x=s[x][1];
137 }
138 }
139 return y;
140 }
141
142 int Find(int v)
143 {
144 int x=root;
145 while(true)
146 {
147 if(t[x]==v) return x;
148 else x=s[x][v>=t[x]];
149 }
150 return -1;
151 }
152
153 int Rank(int v)
154 {
155 int x=root;
156 int r=0;
157 while(x)
158 {
159 if(v>t[x])
160 {
161 r+=tot[s[x][0]]+1;
162 x=s[x][1];
163 }
164 else
165 x=s[x][0];
166 }
167 return r;
168 }
169
170 void Delete(int x)
171 {
172 while(s[x][0] || s[x][1])
173 {
174 if(s[x][0]) rot(s[x][0]);
175 else rot(s[x][1]);
176 }
177
178 if(!f[x]) root=0;
179 else
180 s[f[x]][x==s[f[x]][1]]=0;
181
182 x=f[x];
183 while(x) tot[x]--,x=f[x];
184 }
185
186 int Prefix(int v)
187 {
188 int x=root;
189 int r=-INF;
190 while(x)
191 {
192 if(t[x]<v) r=t[x];
193 x=s[x][v>t[x]];
194 }
195 return r;
196 }
197
198 int Suffix(int v)
199 {
200 int x=root;
201 int r=INF;
202 while(x)
203 {
204 if(t[x]>v) r=t[x];
205 x=s[x][v>=t[x]];
206 }
207 return r;
208 }
209
210 int a[105000];
211
212 int main()
213 {
214 srand(23333);
215
216 n=getint();
217 for(int i=0;i<n;i++)
218 {
219 int c=getint();
220 switch(c)
221 {
222 case 1: Insert(getint()); break;
223 case 2: Delete(Find(getint())); break;
224 case 3: printf("%d\n",Rank(getint())+1); break;
225 case 4: printf("%d\n",t[FindRank(getint())]); break;
226 case 5: printf("%d\n",Prefix(getint())); break;
227 default: printf("%d\n",Suffix(getint())); break;
228 }
229 }
230
231 return 0;
232 }
线段树
AC BZOJ 3212 A Simple Problem 经典题
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21
22 using namespace std;
23
24 inline int getint()
25 {
26 int res=0;
27 char c=getchar();
28 bool mi=false;
29 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
30 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
31 return mi ? -res : res;
32 }
33 inline ll getll()
34 {
35 ll res=0;
36 char c=getchar();
37 bool mi=false;
38 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
39 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
40 return mi ? -res : res;
41 }
42
43 //==============================================================================
44 //==============================================================================
45 //==============================================================================
46 //==============================================================================
47
48
49 int n,m;
50 int a[105000];
51 ll t[405000];
52 ll tag[405000];
53 void Build(int x=1,int l=0,int r=n-1)
54 {
55 if(l==r) { t[x]=a[l]; return ; }
56 int mid=(l+r)>>1;
57 Build(x<<1,l,mid); Build(x<<1|1,mid+1,r);
58 t[x]=t[x<<1]+t[x<<1|1];
59 }
60 int cl,cr,cv;
61 void Change(int x=1,int l=0,int r=n-1)
62 {
63 if(cr<l || r<cl) return ;
64 if(cl<=l && r<=cr) { tag[x]+=cv; return ; }
65 int mid=(l+r)>>1;
66 Change(x<<1,l,mid),Change(x<<1|1,mid+1,r);
67 t[x]=t[x<<1]+tag[x<<1]*(mid-l+1)+t[x<<1|1]+tag[x<<1|1]*(r-mid);
68 }
69 int ql,qr;
70 ll Query(int x=1,int l=0,int r=n-1)
71 {
72 if(qr<l || r<ql) return 0;
73 if(ql<=l && r<=qr) return t[x]+tag[x]*(r-l+1);
74 int mid=(l+r)>>1;
75 return Query(x<<1,l,mid)+Query(x<<1|1,mid+1,r)+
76 tag[x]*(min(r,qr)-max(l,ql)+1);
77 }
78 int main()
79 {
80 n=getint();
81 m=getint();
82 for(int i=0;i<n;i++)
83 a[i]=getint();
84 Build();
85 for(int i=0;i<m;i++)
86 {
87 char c=getchar();
88 while(c!='Q' && c!='C') c=getchar();
89 if(c=='C')
90 {
91 cl=getint()-1;
92 cr=getint()-1;
93 cv=getint();
94 Change();
95 }
96 else //if(c=='Q')
97 {
98 ql=getint()-1;
99 qr=getint()-1;
100 printf("%lld\n",Query());
101 }
102 }
103
104 return 0;
105 }
区间加,区间求和.永久性lazytag.常数大概是普通线段树的四分之一.......
AC BZOJ 3685 用线段树做平衡树查询
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21 typedef long double ldb;
22
23 using namespace std;
24
25 inline int getint()
26 {
27 int res=0;
28 char c=getchar();
29 bool mi=false;
30 while((c<'0' || c>'9')/* && !feof(stdin)*/) mi=(c=='-'),c=getchar();
31 while('0'<=c && c<='9'/* && !feof(stdin)*/) res=res*10+c-'0',c=getchar();
32 return mi ? -res : res;
33 }
34 inline ll getll()
35 {
36 ll res=0;
37 char c=getchar();
38 bool mi=false;
39 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
40 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
41 return mi ? -res : res;
42 }
43
44 //==============================================================================
45 //==============================================================================
46 //==============================================================================
47 //==============================================================================
48
49 int n;
50 int L,R;
51 int t[4005000];
52
53 int cp,cv;
54 void Change(int x=1,int l=L,int r=R)
55 {
56 if(l==r) { t[x]=cv; return ; }
57 int mid=(l+r)>>1;
58 if(cp<=mid) Change(x<<1,l,mid);
59 else Change(x<<1|1,mid+1,r);
60 t[x]=t[x<<1]+t[x<<1|1];
61 }
62
63 int GetMin(int x=1,int l=L,int r=R)
64 {
65 if(!t[x]) return -1;
66 while(l!=r)
67 {
68 int mid=(l+r)>>1;
69 if(t[x<<1]) { r=mid; x<<=1; }
70 else { l=mid+1; x=x<<1|1; }
71 }
72 return l;
73 }
74
75 int GetMax(int x=1,int l=L,int r=R)
76 {
77 if(!t[x]) return -1;
78 while(l!=r)
79 {
80 int mid=(l+r)>>1;
81 if(t[x<<1|1]) { l=mid+1; x=x<<1|1; }
82 else { r=mid; x<<=1; }
83 }
84 return l;
85 }
86
87 int Exist(int p,int x=1,int l=L,int r=R)
88 {
89 if(!t[x]) return -1;
90 while(l!=r)
91 {
92 int mid=(l+r)>>1;
93 if(p<=mid) { x<<=1; r=mid; }
94 else { x=x<<1|1; l=mid+1; }
95 if(!t[x]) return -1;
96 }
97 return 1;
98 }
99
100 int Prefix(int v,int x=1,int l=L,int r=R)
101 {
102 int y=0,yl=0,yr=0;
103 while(l!=r)
104 {
105 int mid=(l+r)>>1;
106 if(v<=mid) { x<<=1; r=mid; }
107 else
108 {
109 if(t[x<<1]) { y=x<<1; yl=l; yr=mid; }
110 x=x<<1|1; l=mid+1;
111 }
112 }
113 return y ? GetMax(y,yl,yr) : -1;
114 }
115
116 int Suffix(int v,int x=1,int l=L,int r=R)
117 {
118 int y=0,yl=0,yr=0;
119 while(l!=r)
120 {
121 int mid=(l+r)>>1;
122 if(v<=mid)
123 {
124 if(t[x<<1|1]) { y=x<<1|1; yl=mid+1; yr=r; }
125 x<<=1; r=mid;
126 }
127 else { x=x<<1|1; l=mid+1; }
128 }
129 return y ? GetMin(y,yl,yr) : -1;
130 }
131
132 int main()
133 {
134 n=getint();
135 L=-1; R=n+1;
136 int m=getint();
137 for(int i=0;i<m;i++)
138 {
139 int c=getint();
140 switch(c)
141 {
142 case 1: cp=getint(); cv=1; Change(); break;
143 case 2: cp=getint(); cv=0; Change(); break;
144 case 3: printf("%d\n",GetMin()); break;
145 case 4: printf("%d\n",GetMax()); break;
146 case 5: printf("%d\n",Prefix(getint())); break;
147 case 6: printf("%d\n",Suffix(getint())); break;
148 case 7: printf("%d\n",Exist(getint()));
149 default:break;
150 }
151 }
152
153 return 0;
154 }
注意前驱和后继的写法:
想象一下前缀的搜索过程,我们先搜索到询问数字的代表节点,然后回退,如果左子树非空就进入这棵左子树并一直往右往下走.
先写一个GetMax和GetMin函数,表示找到某一棵子树中最靠右的存在的节点.
然后查询前驱(或后继)时,考虑记下一个"最右(左)可行子树y".就是说
我们遍历从根到所查询的值的节点的路径,如果遍历过程中往右(左)走了,并且当前节点左(右)子树非空,
那么拿当前节点的左(右)子树替换掉y,这样我们就得到了"最靠右(左)的可行子树".
然后在这棵子树中GetMax(GetMin)就行了.
可持久化线段树
AC VIJOS 1081 野生动物园
一道非常裸的区间k大
1 const int INF=(1<<30)-1;
2
3 struct node
4 {
5 int t;
6 node*l,*r;
7 node(){ t=0; l=r=NULL; }
8
9 void update()
10 { t=l->t+r->t; }
11 }pool[4000000];
12 int nt;
13 node*newnode()
14 { return &pool[nt++]; }
15
16 node*nil;
17
18 node*root[100050];
19
20 void SegmentTreeInit(int size)
21 {
22 nil=newnode();
23 nil->l=nil->r=nil;
24 nil->t=0;
25 for(int i=0;i<=size;i++)
26 root[i]=nil;
27 }
28
29 int cp;
30 node*Change(node*x,node*y,int l,int r)
31 {
32 if(cp<l || r<cp) return y;
33 x=newnode();
34 if(l==r) { x->t=1+y->t; return x; }
35 int mid=(l+r)>>1;
36 x->l=Change(x->l,y->l,l,mid);
37 x->r=Change(x->r,y->r,mid+1,r);
38 x->update();
39 return x;
40 }
41 void Change(int i,int j,int pos)
42 { cp=pos; root[i]=Change(nil,root[j],0,INF); }
43
44 int Query(int ql,int qr,int k)
45 {
46 node*x=root[ql],*y=root[qr];
47 int l=0,r=INF;
48 while(l!=r)
49 {
50 int mid=(l+r)>>1;
51 if( k<= x->l->t - y->l->t )
52 r=mid,x=x->l,y=y->l;
53 else
54 {
55 k-=x->l->t-y->l->t;
56 l=mid+1,x=x->r,y=y->r;
57 }
58 }
59 return l;
60 }
61
62
63
64 int n;
65
66
67
68 int main()
69 {
70
71 int q;
72 scanf("%d",&n);
73 scanf("%d",&q);
74
75 SegmentTreeInit(n);
76
77
78 for(int i=0;i<n;i++)
79 {
80 int c;
81 scanf("%d",&c);
82 cp=c;
83 root[i+1]=Change(root[i+1],root[i],0,INF);
84 }
85
86
87 for(int i=0;i<q;i++)
88 {
89 int a,b,k;
90 scanf("%d%d%d",&a,&b,&k);
91 printf("%d\n",Query(b,a-1,k));
92 }
93
94 return 0;
95 }
要点1.使用nil节点可以省一点代码
要点2.千万注意空间开销.一般为nlogv级别,数组经常开上百万(懒得写离散化系列)
要点3.注意前缀和的写法. tree[R]-tree[L-1]. 这就要求root[0]=nil.
要点4.智商捉急表示普通查找操作总是写错...splay也一样.....思考...思考......写之前一定要想好....
AC BZOJ 3932 加强版的主席树,以时间轴为询问区间,插入一个值,删除一个值.
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21
22 using namespace std;
23
24 inline int getint()
25 {
26 int res=0;
27 char c=getchar();
28 bool mi=false;
29 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
30 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
31 return mi ? -res : res;
32 }
33 inline ll getll()
34 {
35 ll res=0;
36 char c=getchar();
37 bool mi=false;
38 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
39 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
40 return mi ? -res : res;
41 }
42
43 //==============================================================================
44 //==============================================================================
45 //==============================================================================
46 //==============================================================================
47
48 const int INF=10000001;
49
50 struct node*nil;
51 struct node
52 {
53 int t;
54 ll v;
55 node*l,*r;
56
57 void update()
58 { t = l->t + r->t; v = l->v + r->v; }
59
60 };
61 int cnt=10000;
62 node*nt;
63 node*newnode()
64 {
65 if(cnt==10000){ cnt=0; nt=new node[10000]; }
66 nt->t=nt->v=0;
67 nt->l=nt->r=nil;
68 cnt++;
69 return nt++;
70 }
71
72 int n,m;
73
74 node*root[105000];
75
76 struct operation
77 {
78 int p; //time block
79 int v; //value
80 bool type; //0:add 1:dec
81
82 }op[205000];
83
84 bool cmp(const operation&a,const operation&b)
85 { return a.p<b.p; }
86
87
88 int cp,cv;
89 node*Change(node*y,int l,int r)
90 {
91 if(cp<l || r<cp) return y;
92 node*x=newnode();
93 if(l==r) { x->t=y->t+cv; x->v=y->v+cp*cv; return x; }
94 int mid=(l+r)>>1;
95 x->l=Change(y->l,l,mid);
96 x->r=Change(y->r,mid+1,r);
97 x->update();
98 return x;
99 }
100
101 node*Change(int p,int v,node*pre)
102 { cp=p; cv=v; return Change(pre,0,INF); }
103
104
105 int ql,qr;
106
107 ll rest;
108 ll last;
109 int Query(int k,node*x) //x-y. query for the kth node.
110 {
111 if(x->t<k) return INF;
112 int l=0,r=INF;
113 while(l!=r)
114 {
115 int mid=(l+r)>>1;
116 if(k<=x->l->t)
117 {
118 x=x->l;
119 r=mid;
120 }
121 else
122 {
123 k-=x->l->t;
124 x=x->r;
125 l=mid+1;
126 }
127 }
128 rest=x->t-k;
129 last=x->v/x->t;
130 return l;
131 }
132
133 ll Query(node*x,int l=0,int r=INF) //x-y. query for sum.
134 {
135 if(qr<l || r<ql) return 0;
136 if(ql<=l && r<=qr) return x->v;
137 int mid=(l+r)>>1;
138 return Query(x->l,l,mid) + Query(x->r,mid+1,r);
139 }
140
141 int main()
142 {
143 nil=newnode();
144 nil->l=nil->r=nil;
145
146 n=getint();
147 m=getint();
148 for(int i=0;i<n;i++)
149 {
150 int a=getint();
151 int b=getint();
152 int c=getint();
153 op[i].p=a; op[i].v=c; op[i].type=0;
154 op[i+n].p=b+1; op[i+n].v=c; op[i+n].type=1;
155 }
156
157 for(int i=0;i<=103000;i++) root[i]=nil;
158
159 sort(op,op+2*n,cmp);
160
161 int cur=0;
162 for(int i=1;i<=103000;i++)
163 {
164 root[i]=root[i-1];
165 while(op[cur].p==i && cur<2*n)
166 {
167 root[i]=Change(op[cur].v,op[cur].type==0 ? 1 : -1,root[i]);
168 cur++;
169 }
170 }
171
172 ll pre=1;
173
174 ql=0;
175 for(int i=0;i<m;i++)
176 {
177 int p=getint();
178 int a=getint();
179 int b=getint();
180 int c=getint();
181 ll k=((ll)a*pre+(ll)b)%c+1;
182 qr=Query(k,root[p]);
183 printf("%lld\n",pre=(Query(root[p])-rest*last));
184 }
185
186
187 return 0;
188 }
所以说啊....我写的可持久化线段树也没那么容易RE啊.....COT怎么就是A不了呢.....
WA了一发是因为没有想清楚前k个的含义,那些值与第k个元素相等但不计入结果的元素没有考虑进去....
哎......这个算智商么......
AC BZOJ3674 可持久化并查集加强版
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21
22 using namespace std;
23
24 inline int getint()
25 {
26 int res=0;
27 char c=getchar();
28 bool mi=false;
29 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
30 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
31 return mi ? -res : res;
32 }
33 inline ll getll()
34 {
35 ll res=0;
36 char c=getchar();
37 bool mi=false;
38 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
39 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
40 return mi ? -res : res;
41 }
42
43 //==============================================================================
44 //==============================================================================
45 //==============================================================================
46 //==============================================================================
47
48
49 struct node*nil;
50 struct node
51 {
52 int v;
53 node*l,*r;
54 };
55 int ncnt=4000;
56 node*nt;
57 node*newnode()
58 {
59 if(ncnt==4000) { ncnt=0; nt=new node[4000]; }
60 nt->v=0;
61 nt->l=nt->r=nil;
62 ncnt++;
63 return nt++;
64 }
65
66 node*root[405000]; //operations.
67
68 int n,m;
69
70 int cp,cv;
71 node*Change(node*y,int l=0,int r=n+1)
72 {
73 if(cp<l || r<cp) return y;
74 node*x=newnode();
75 if(l==r) { x->v=cv; return x; }
76 int mid=(l+r)>>1;
77 x->l=Change(y->l,l,mid);
78 x->r=Change(y->r,mid+1,r);
79 return x;
80 }
81
82 int Get(node*x,int p)
83 {
84 int l=0,r=n+1;
85 while(l!=r)
86 {
87 int mid=(l+r)>>1;
88 if(p<=mid)
89 x=x->l,r=mid;
90 else
91 x=x->r,l=mid+1;
92 }
93 return x->v;
94 }
95
96 node*Build(int l=0,int r=n+1)
97 {
98 node*x=newnode();
99 if(l==r) { x->v=l; return x; }
100 int mid=(l+r)>>1;
101 x->l=Build(l,mid);
102 x->r=Build(mid+1,r);
103 return x;
104 }
105
106 int findf(node*&t,int x)
107 {
108 int f=Get(t,x);
109 if(f==x) return x;
110 int ff=findf(t,f);
111 cp=x; cv=ff;
112 t=Change(t);
113 return ff;
114 }
115
116 int main()
117 {
118 nil=newnode();
119 nil->v=0;
120 nil->l=nil->r=nil;
121
122 n=getint();
123 m=getint();
124
125 root[0]=Build();
126
127 int lastans=0;
128
129 for(int i=1;i<=m;i++)
130 {
131 int c=getint();
132
133 if(c==1) //Merge
134 {
135 int a=getint();
136 int b=getint();
137
138 root[i]=root[i-1];
139 int fa=findf(root[i],a);
140 int fb=findf(root[i],b);
141 if(fa!=fb)
142 {
143 cp=fa;
144 cv=fb;
145 root[i]=Change(root[i]);
146 }
147 }
148 else if(c==2) //Back
149 {
150 int k=getint()^lastans;
151 root[i]=root[k];
152 }
153 else if(c==3) //Query
154 {
155 int a=getint()^lastans;
156 int b=getint()^lastans;
157 root[i]=root[i-1];
158 int fa=findf(root[i],a);
159 int fb=findf(root[i],b);
160 printf("%d\n",lastans=(fa==fb));
161 }
162 }
163
164 return 0;
165 }
好吧,不知怎么的就A了.....
加强版的话,不加路径压缩会TLE哦.....
AC BZOJ2588 SPOJ:COT Count On A Tree
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21 typedef long double ldb;
22
23 using namespace std;
24
25 inline int getint()
26 {
27 int res=0;
28 char c=getchar();
29 bool mi=false;
30 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
31 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
32 return mi ? -res : res;
33 }
34 inline ll getll()
35 {
36 ll res=0;
37 char c=getchar();
38 bool mi=false;
39 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
40 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
41 return mi ? -res : res;
42 }
43
44 //==============================================================================
45 //==============================================================================
46 //==============================================================================
47 //==============================================================================
48
49 struct edge
50 { int in; edge*nxt; };
51 int ecnt=2000; edge*et;
52 edge*eds[105000];
53 void addedge(int a,int b)
54 {
55 if(ecnt==2000) { ecnt=0; et=new edge[2000]; }
56 et->in=b; et->nxt=eds[a]; eds[a]=et++; ecnt++;
57 }
58 #define FOREACH_EDGE(e,x) for(edge*e=eds[x];e;e=e->nxt)
59
60 int v[105000]; int lim=0;
61
62 struct node*nil;
63 struct node
64 { int t; node*l,*r; void update(){t=l->t+r->t;} };
65 int ncnt=4000; node*nt;
66 node*newnode()
67 {
68 if(ncnt==4000) { ncnt=0; nt=new node[4000]; }
69 ncnt++; return nt++;
70 }
71 int cp;
72 node*Insert(node*y,int l=0,int r=lim-1)
73 {
74 node*x=newnode();
75 if(l==r) { x->l=x->r=nil; x->t=y->t+1; return x; }
76 int mid=(l+r)>>1;
77 x->l= cp<=mid ? Insert(y->l,l,mid) : y->l;
78 x->r= cp>mid ? Insert(y->r,mid+1,r) : y->r;
79 x->update(); return x;
80 }
81
82 int n,m,q;
83
84 int a[105000];
85 int dep[105000];
86 int f[105000];
87 node*root[105000];
88 int ch[105000]; int chtot=0;
89 int h[105000];
90
91 int Build(int x)
92 {
93 //printf("%d\n",x);
94 int sum=0;
95 int mxp=0;
96 int mx=0;
97 FOREACH_EDGE(e,x)
98 if(e->in!=f[x])
99 {
100 dep[e->in]=dep[x]+1;
101 f[e->in]=x;
102 cp=a[e->in]; root[e->in]=Insert(root[x]);
103 int v=Build(e->in);
104 if(v>mx) mx=v,mxp=e->in;
105 sum+=v;
106 }
107
108 if(mxp) ch[x]=ch[mxp];
109 else ch[x]=chtot++;
110 h[ch[x]]=x;
111
112 return sum+1;
113 }
114
115 int getlca(int a,int b)
116 {
117 while(ch[a]!=ch[b])
118 {
119 if(dep[h[ch[a]]]<dep[h[ch[b]]]) swap(a,b);
120 a=f[h[ch[a]]];
121 }
122 return dep[a]<dep[b] ? a : b;
123 }
124
125 int Query(int a,int b,int k)
126 {
127 node*c[4];
128 c[0]=root[a];
129 c[1]=root[b];
130 int lca=getlca(a,b);
131 c[2]=root[lca];
132 c[3]=root[f[lca]];
133 int l=0,r=lim-1;
134 while(l!=r)
135 {
136 int mid=(l+r)>>1;
137 int lv=c[0]->l->t + c[1]->l->t - c[2]->l->t -c[3]->l->t;
138 if(k<=lv)
139 {
140 for(int i=0;i<4;i++) c[i]=c[i]->l;
141 r=mid;
142 }
143 else
144 {
145 k-=lv;
146 for(int i=0;i<4;i++) c[i]=c[i]->r;
147 l=mid+1;
148 }
149 }
150 return l;
151 }
152
153 int main()
154 {
155 nil=new node;
156 nil->t=0;
157 nil->l=nil->r=nil;
158
159 n=getint();
160 m=n-1;
161 q=getint();
162 for(int i=0;i<n;i++) v[i]=a[i]=getint();
163 sort(v,v+n);
164 lim=int(unique(v,v+n)-v);
165 for(int i=0;i<n;i++)
166 a[i]=int(lower_bound(v,v+lim,a[i])-v);
167
168 for(int i=0;i<m;i++)
169 {
170 int a=getint()-1;
171 int b=getint()-1;
172 addedge(a,b); addedge(b,a);
173 }
174 addedge(n,0); //node n is a sepcial dummy node.
175 root[n]=nil; f[n]=n;
176 Build(n);
177
178 int lst=0;
179 for(int i=0;i<q;i++)
180 {
181 int a=getint();
182 int b=getint()-1;
183 int k=getint();
184 a=a^lst;
185 a--;
186 printf("%d",lst=v[Query(a,b,k)]);
187 if(i!=q-1) printf("\n");
188 }
189
190 return 0;
191 }
终于A了啊.....
离散化 + HLD-LCA 拿到了rank3 2333333
树套树
AC VIJOS 1665
树状数组 套 动态开点的权值线段树
题目就是裸的带修改区间K大
写了一个多小时...调了大概....一个半小时?
树状数组怎么写都快忘记了........
由于懒得离散化......所以.....开了一个巨大的数组.......
VJ的内存限制不错....先把数组从400W改到800W...还是RE..怒而改到1.3kW...AC了.....
看了看空间消耗.....160M.....
这告诉我们千万不要忽视离散化的力量! 千万不要忽视常数空间!
但是我还是很懒=w=能不写离散化就不写离散化=w=
好吧......
下面是代码.....
附带一大版的文件头以及调试信息2333
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21
22 using namespace std;
23
24 inline int getint()
25 {
26 int res=0;
27 char c=getchar();
28 bool mi=false;
29 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
30 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
31 return mi ? -res : res;
32 }
33 inline ll getll()
34 {
35 ll res=0;
36 char c=getchar();
37 bool mi=false;
38 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
39 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
40 return mi ? -res : res;
41 }
42
43 db eps=1e-18;
44 inline bool feq(db a,db b)
45 { return fabs(a-b)<eps; }
46
47 inline int avg(const int a,const int b)
48 { return a+((b-a)>>1); }
49
50 //==============================================================================
51 //==============================================================================
52 //==============================================================================
53 //==============================================================================
54
55 const int INF=(1<<30)-1;
56
57 int n;
58 struct node*nil;
59 struct node
60 {
61 int v; //total
62 node*l,*r;
63 void update()
64 { v=l->v+r->v; }
65 }pool[13000000];
66 node*nt=pool;
67 node*newnode()
68 {
69 nt->l=nt->r=nil;
70 nt->v=0;
71 return nt++;
72 }
73
74 int cp,cv;
75
76 //Sub segment trees
77 struct SegmentTree
78 {
79 node*root;
80
81 node*Change(node*x,int l=0,int r=INF)
82 {
83 if(cp<l || r<cp) return x;
84 if(x==nil) x=newnode();
85 if(l==r) { x->v+=cv; return x; }
86 int mid=avg(l,r);
87 x->l=Change(x->l,l,mid);
88 x->r=Change(x->r,mid+1,r);
89 x->update();
90 return x;
91 }
92
93 void Set(int p,int v)
94 {
95 if(root<pool) root=nil;
96 cp=p;
97 cv=v;
98 root=Change(root);
99 }
100 };
101
102 //original segment tree
103 //performed as tree array
104
105 #define bt(x) (x&-x)
106
107 int a[1000000]; //this array must be stay here....
108 SegmentTree t[1000000];
109 void Change(int p,int s,int v) //location of point, value of point, delete or add in.
110 { for(int i=p;i<=n;i+=bt(i)) t[i].Set(s,v); }
111
112 node*c[1000];
113 int adt,ct;
114
115 int Query(int l,int r,int k) //find the element which is rank k.
116 {
117 adt=0;
118
119 for(int i=r;i>0;i-=bt(i))
120 c[adt++]=t[i].root;
121
122 ct=adt;
123 for(int i=l-1;i>0;i-=bt(i))
124 c[ct++]=t[i].root;
125
126 //we perform add when i<adt, and than dec when adt<=i<ct
127
128
129 l=0,r=INF;
130 while(l!=r)
131 {
132 //for(int i=0;i<ct;i++)
133 //cout<<c[i]<<' '; cout<<endl; cout<<l<<' '<<r<<endl; cout<<endl;
134
135 int mid=avg(l,r);
136 int clv=0; //current node's left node count.
137
138 for(int i=0;i<adt;i++)
139 clv+=c[i]->l->v;
140 for(int i=adt;i<ct;i++)
141 clv-=c[i]->l->v;
142
143 if(k<=clv) //the element we want find is on the left block
144 {
145 for(int i=0;i<ct;i++)
146 c[i]=c[i]->l;
147 r=mid;
148 }
149 else
150 {
151 for(int i=0;i<ct;i++)
152 c[i]=c[i]->r;
153 k-=clv;
154 l=mid+1;
155 }
156 }
157
158 return l;
159 }
160
161 int q;
162
163 int main()
164 {
165 nil=newnode();
166 nil->l=nil->r=nil;
167 nil->v=0;
168
169 n=getint();
170 q=getint();
171 for(int i=0;i<n;i++)
172 Change(i+1,a[i+1]=getint(),1);
173
174 for(int i=0;i<q;i++)
175 {
176 char c[5];
177 scanf("%s",c);
178 if(c[0]=='C')
179 {
180 int i=getint();
181 int v=getint();
182 Change(i,a[i],-1);
183 Change(i,a[i]=v,1);
184 }
185 else
186 {
187 int i=getint();
188 int j=getint();
189 int k=getint();
190 printf("%d\n",Query(i,j,k));
191 }
192 }
193
194 return 0;
195 }
196
197
需要注意的地方:
1.树状数组什么的一级结构别写错了啊啊啊啊啊啊
2.既然是动态开点(即便离散化了也给我动态!绝对不要写静态的树套在另外的树里面!)....
那么,我们只需要记录每棵树的根节点就好了.其它节点在访问的时候会碰到.
3.嗯....(结构相同的)线段树是可加的.......所以不要再去写二分,直接在加起来的那棵树上隐式二分即可.详见代码.可以降低一个log的复杂度.
4.二分的界,以及二分后的操作(k-=...)一定要考虑清楚.
2015年3月4日更新
<5.不知道为什么, 用@iwtwiioi在某些地方的AC代码交到VJ,TLE了...就AC了我第一次提交没有RE的那两个范围较小的点...... http://www.cnblogs.com/iwtwiioi/p/3929957.html>
嘛,以上TLE的原因是在BZOJ上原题的数据范围是n<=1W,VIJOS上是N<=5W.....噗......不知道当时看走眼了还是什么的囧
树状数组套动态开点的权值线段树
AC BZOJ 3196 tyvj 二逼平衡树
传说中都用树状数组套Treap.....然而我是蒟蒻不会套平衡树......所以写了线段树.....1A.....
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21
22 using namespace std;
23
24 inline int getint()
25 {
26 int res=0;
27 char c=getchar();
28 bool mi=false;
29 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
30 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
31 return mi ? -res : res;
32 }
33 inline ll getll()
34 {
35 ll res=0;
36 char c=getchar();
37 bool mi=false;
38 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
39 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
40 return mi ? -res : res;
41 }
42
43 //==============================================================================
44 //==============================================================================
45 //==============================================================================
46 //==============================================================================
47
48
49
50 const int INF=100000001;
51
52
53 struct node*nil;
54 struct node
55 {
56 int v;
57 node*l,*r;
58 };
59 int ncnt=5000;
60 node*nt;
61 node*newnode()
62 {
63 if(ncnt==5000) { ncnt=0; nt=new node[5000]; }
64 nt->l=nt->r=nil;
65 ncnt++; return nt++;
66 }
67
68 int ip,iv;
69 void Insert(node*&x,int l=-1,int r=INF)
70 {
71 if(ip<l || r<ip) return ;
72 if(x==nil) x=newnode();
73 int mid=(l+r)>>1;
74 if(l==r) { x->v+=iv; return ; }
75 Insert(x->l,l,mid);
76 Insert(x->r,mid+1,r);
77 x->v = x->l->v + x->r->v;
78 }
79
80 int n,m;
81 int a[50050]; // true array
82
83 node*t[50050];
84 void Change(int loc,int p,int v)
85 {
86 ip=p; iv=v;
87 for(int i=loc;i<=n;i+=(i&-i))
88 Insert(t[i]);
89 }
90
91 node*p[1000];
92 node*s[1000];
93 int sp,ss;
94 inline void QueryBIT(int L,int R)
95 {
96 sp=ss=0;
97 for(int i=L-1;i;i-=(i&-i)) s[ss++]=t[i];
98 for(int i=R;i;i-=(i&-i)) p[sp++]=t[i];
99 }
100 inline void GoLeft()
101 {
102 for(int i=0;i<sp;i++) p[i]=p[i]->l;
103 for(int i=0;i<ss;i++) s[i]=s[i]->l;
104 }
105 inline void GoRight()
106 {
107 for(int i=0;i<sp;i++) p[i]=p[i]->r;
108 for(int i=0;i<ss;i++) s[i]=s[i]->r;
109 }
110 inline int CountLeft()
111 {
112 int res=0;
113 for(int i=0;i<sp;i++) res+=p[i]->l->v;
114 for(int i=0;i<ss;i++) res-=s[i]->l->v;
115 return res;
116 }
117 inline int CountRight()
118 {
119 int res=0;
120 for(int i=0;i<sp;i++) res+=p[i]->r->v;
121 for(int i=0;i<ss;i++) res-=s[i]->r->v;
122 return res;
123 }
124
125 int GetRank(int v) //Query the count of numbers smaller than v.
126 {
127 int l=-1,r=INF;
128 int res=0;
129 while(l!=r)
130 {
131 int mid=(l+r)>>1;
132 if(v<=mid) { GoLeft(); r=mid; }
133 else { res+=CountLeft(); GoRight(); l=mid+1; }
134 }
135 return res;
136 }
137
138 int FindRank(int k) //find the number with rank k.
139 {
140 int l=-1,r=INF;
141 while(l!=r)
142 {
143 int mid=(l+r)>>1;
144 int t=CountLeft();
145 if(k<=t) { GoLeft(); r=mid; }
146 else { k-=t; GoRight(); l=mid+1; }
147 }
148 return l;
149 }
150
151 int GetPrefix(int L,int R,int v)
152 {
153 QueryBIT(L,R);
154 int t=GetRank(v);
155 QueryBIT(L,R);
156 return FindRank(t);
157 }
158
159 int GetSuffix(int L,int R,int v)
160 {
161 QueryBIT(L,R);
162 int t=GetRank(v+1);
163 QueryBIT(L,R);
164 return FindRank(t+1);
165 }
166
167 int main()
168 {
169 nil=new node;
170 nil->l=nil->r=nil;
171 nil->v=0;
172
173 n=getint();
174 m=getint();
175
176 for(int i=0;i<=n;i++)
177 t[i]=nil;
178
179 for(int i=1;i<=n;i++)
180 Change(i,a[i]=getint(),1);
181
182 for(int i=0;i<m;i++)
183 {
184 int c=getint();
185 int b=getint();
186 int d=getint();
187 if(c==1) //Get Rank
188 {
189 int v=getint();
190 QueryBIT(b,d);
191 printf("%d\n",GetRank(v)+1);
192 }
193 else if(c==2) //Find by Rank
194 {
195 int k=getint();
196 QueryBIT(b,d);
197 printf("%d\n",FindRank(k));
198 }
199 else if(c==3) //Change
200 {
201 Change(b,a[b],-1);
202 Change(b,a[b]=d,1);
203 }
204 else if(c==4) //Prefix
205 {
206 int v=getint();
207 printf("%d\n",GetPrefix(b,d,v));
208 }
209 else if(c==5) //Suffix
210 {
211 int v=getint();
212 printf("%d\n",GetSuffix(b,d,v));
213 }
214 }
215
216 return 0;
217 }
运行时间为3.46s. 这个找前驱和后继的操作简直SXBK......
先统计一下比那个数小的数的个数(就是找排名)......然后再找到排名等于那个数的数......后继差不多.....
似乎比较慢? 没有开离散化....内存用得很多.....但是比treap快2333333
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21
22 using namespace std;
23
24 inline int getint()
25 {
26 int res=0;
27 char c=getchar();
28 bool mi=false;
29 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
30 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
31 return mi ? -res : res;
32 }
33 inline ll getll()
34 {
35 ll res=0;
36 char c=getchar();
37 bool mi=false;
38 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
39 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
40 return mi ? -res : res;
41 }
42
43 //==============================================================================
44 //==============================================================================
45 //==============================================================================
46 //==============================================================================
47
48
49 struct node*nil;
50 struct node
51 {
52 int v;
53 node*l,*r;
54 };
55 int ncnt=5000;
56 node*nt;
57 node*newnode()
58 {
59 if(ncnt==5000) { ncnt=0; nt=new node[5000]; }
60 nt->l=nt->r=nil;
61 ncnt++; return nt++;
62 }
63
64 int lim;
65
66 int ip,iv;
67 void Insert(node*&x,int l=0,int r=lim-1)
68 {
69 if(ip<l || r<ip) return ;
70 if(x==nil) x=newnode();
71 int mid=(l+r)>>1;
72 if(l==r) { x->v+=iv; return ; }
73 Insert(x->l,l,mid);
74 Insert(x->r,mid+1,r);
75 x->v = x->l->v + x->r->v;
76 }
77
78 int n,m;
79 int a[50050]; // true array
80
81 node*t[50050];
82 void Change(int loc,int p,int v)
83 {
84 ip=p; iv=v;
85 for(int i=loc;i<=n;i+=(i&-i))
86 Insert(t[i]);
87 }
88
89 node*p[1000];
90 node*s[1000];
91 int sp,ss;
92 inline void QueryBIT(int L,int R)
93 {
94 sp=ss=0;
95 for(int i=L-1;i;i-=(i&-i)) s[ss++]=t[i];
96 for(int i=R;i;i-=(i&-i)) p[sp++]=t[i];
97 }
98 inline void GoLeft()
99 {
100 for(int i=0;i<sp;i++) p[i]=p[i]->l;
101 for(int i=0;i<ss;i++) s[i]=s[i]->l;
102 }
103 inline void GoRight()
104 {
105 for(int i=0;i<sp;i++) p[i]=p[i]->r;
106 for(int i=0;i<ss;i++) s[i]=s[i]->r;
107 }
108 inline int CountLeft()
109 {
110 int res=0;
111 for(int i=0;i<sp;i++) res+=p[i]->l->v;
112 for(int i=0;i<ss;i++) res-=s[i]->l->v;
113 return res;
114 }
115 inline int CountRight()
116 {
117 int res=0;
118 for(int i=0;i<sp;i++) res+=p[i]->r->v;
119 for(int i=0;i<ss;i++) res-=s[i]->r->v;
120 return res;
121 }
122
123 int GetRank(int v) //Query the count of numbers smaller than v.
124 {
125 int l=0,r=lim-1;
126 int res=0;
127 while(l!=r)
128 {
129 int mid=(l+r)>>1;
130 if(v<=mid) { GoLeft(); r=mid; }
131 else { res+=CountLeft(); GoRight(); l=mid+1; }
132 }
133 return res;
134 }
135
136 int FindRank(int k) //find the number with rank k.
137 {
138 int l=0,r=lim-1;
139 while(l!=r)
140 {
141 int mid=(l+r)>>1;
142 int t=CountLeft();
143 if(k<=t) { GoLeft(); r=mid; }
144 else { k-=t; GoRight(); l=mid+1; }
145 }
146 return l;
147 }
148
149 int GetPrefix(int L,int R,int v)
150 {
151 QueryBIT(L,R);
152 int t=GetRank(v);
153 QueryBIT(L,R);
154 return FindRank(t);
155 }
156
157 int GetSuffix(int L,int R,int v)
158 {
159 QueryBIT(L,R);
160 int t=GetRank(v+1);
161 QueryBIT(L,R);
162 return FindRank(t+1);
163 }
164
165 int op[50050][4];
166 int v[105000];
167 int c;
168
169 int main()
170 {
171 nil=new node;
172 nil->l=nil->r=nil;
173 nil->v=0;
174
175 n=getint();
176 m=getint();
177
178 for(int i=0;i<=n;i++)
179 t[i]=nil;
180
181 for(int i=1;i<=n;i++)
182 v[c++]=a[i]=getint();
183
184 for(int i=0;i<m;i++)
185 {
186 op[i][0]=getint();
187 op[i][1]=getint();
188 op[i][2]=getint();
189 if(op[i][0]!=3) op[i][3]=getint();
190
191 if(op[i][0]==3) v[c++]=op[i][2];
192 else
193 if(op[i][0]!=2) v[c++]=op[i][3];
194 }
195
196 sort(v,v+c);
197 lim=int(unique(v,v+c)-v);
198 for(int i=1;i<=n;i++)
199 a[i]=int(lower_bound(v,v+lim,a[i])-v);
200 for(int i=0;i<m;i++)
201 if(op[i][0]==3) op[i][2]=int(lower_bound(v,v+lim,op[i][2])-v);
202 else
203 if(op[i][0]!=2) op[i][3]=int(lower_bound(v,v+lim,op[i][3])-v);
204
205 for(int i=1;i<=n;i++)
206 Change(i,a[i],1);
207
208 for(int i=0;i<m;i++)
209 {
210 //printf("i:%d ",i);
211 if(op[i][0]==1) //Get Rank
212 {
213 QueryBIT(op[i][1],op[i][2]);
214 printf("%d\n",GetRank(op[i][3])+1);
215 }
216 else if(op[i][0]==2) //Find by Rank
217 {
218 QueryBIT(op[i][1],op[i][2]);
219 printf("%d\n",v[FindRank(op[i][3])]);
220 }
221 else if(op[i][0]==3) //Change
222 {
223 Change(op[i][1],a[op[i][1]],-1);
224 Change(op[i][1],a[op[i][1]]=op[i][2],1);
225 }
226 else if(op[i][0]==4) //Prefix
227 printf("%d\n",v[GetPrefix(op[i][1],op[i][2],op[i][3])]);
228 else if(op[i][0]==5) //Suffix
229 printf("%d\n",v[GetSuffix(op[i][1],op[i][2],op[i][3])]);
230 }
231
232 return 0;
233 }
加离散化之后2.37s....内存少了50M.....
AC BZOJ 3110
权值线段树套常规线段树
1 #include <cstdio> 2 #include <fstream> 3 #include <iostream> 4 5 #include <cstdlib> 6 #include <cstring> 7 #include <algorithm> 8 #include <cmath> 9 10 #include <queue> 11 #include <vector> 12 #include <map> 13 #include <set> 14 #include <stack> 15 #include <list> 16 17 typedef unsigned int uint; 18 typedef long long int ll; 19 typedef unsigned long long int ull; 20 typedef double db; 21 typedef long double ldb; 22 23 using namespace std; 24 25 inline int getint() 26 { 27 int res=0; 28 char c=getchar(); 29 bool mi=false; 30 while((c<'0' || c>'9')/* && !feof(stdin)*/) mi=(c=='-'),c=getchar(); 31 while('0'<=c && c<='9'/* && !feof(stdin)*/) res=res*10+c-'0',c=getchar(); 32 return mi ? -res : res; 33 } 34 inline ll getll() 35 { 36 ll res=0; 37 char c=getchar(); 38 bool mi=false; 39 while(c<'0' || c>'9') mi=(c=='-'),c=getchar(); 40 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar(); 41 return mi ? -res : res; 42 } 43 44 //============================================================================== 45 //============================================================================== 46 //============================================================================== 47 //============================================================================== 48 49 50 struct operation{bool t; int l,r; int v; }op[50050]; 51 int dsv[50050]; int vt; 52 53 //segment tree 54 struct node{ node*l,*r; int t; int tag; }; 55 node*nt; int ncnt=20000; 56 node*newnode() 57 { 58 if(ncnt==20000){ nt=new node[20000]; ncnt=0; } 59 nt->l=nt->r=NULL; nt->t=nt->tag=0; ncnt++; 60 return nt++; 61 } 62 63 int n,m; 64 65 int cl,cr; 66 void Change(node*&x,int l=0,int r=n-1) 67 { 68 if(x==NULL) x=newnode(); 69 if(cl<=l && r<=cr) { x->tag++; return ; } 70 int mid=(l+r)>>1; 71 if(mid>=cl) Change(x->l,l,mid); 72 if(mid<cr) Change(x->r,mid+1,r); 73 x->t = ( x->l ? x->l->t + x->l->tag*(mid-l+1) : 0 ) + 74 ( x->r ? x->r->t + x->r->tag*(r-mid) : 0 ) ; 75 } 76 int ql,qr; 77 int Query(node*x,int l=0,int r=n-1) 78 { 79 if(qr<l || r<ql || x==NULL) return 0; 80 if(ql<=l && r<=qr) { return x->t + x->tag*(r-l+1); } 81 int mid=(l+r)>>1; 82 return Query(x->l,l,mid)+Query(x->r,mid+1,r)+x->tag*(min(qr,r)-max(ql,l)+1) ; 83 } 84 85 node*t[205000]; //outer segment tree 86 87 void Insert(int L,int R,int p,int x=1,int l=0,int r=vt-1) 88 { 89 cl=L; cr=R; 90 while(l!=r) 91 { 92 int mid=(l+r)>>1; 93 Change(t[x]); 94 if(p<=mid) { x<<=1; r=mid; } 95 else { x=x<<1|1; l=mid+1; } 96 } 97 Change(t[x]); 98 } 99 100 int Query(int L,int R,int k,int x=1,int l=0,int r=vt-1) 101 { 102 ql=L; qr=R; 103 while(l!=r) 104 { 105 int mid=(l+r)>>1; 106 int v=Query(t[x<<1|1]); 107 if(k>v) { k-=v; x<<=1; r=mid; } 108 else { x=x<<1|1; l=mid+1; } 109 } 110 return l; 111 } 112 113 int main() 114 { 115 n=getint(); 116 m=getint(); 117 118 for(int i=0;i<m;i++) 119 { 120 op[i].t=getint()-1; 121 op[i].l=getint()-1; 122 op[i].r=getint()-1; 123 op[i].v=getint(); 124 if(!op[i].t) dsv[vt++]=op[i].v; 125 } 126 sort(dsv,dsv+vt); 127 vt=int(unique(dsv,dsv+vt)-dsv); 128 for(int i=0;i<m;i++) if(!op[i].t) 129 { op[i].v=int(lower_bound(dsv,dsv+vt,op[i].v)-dsv); } 130 131 for(int i=0;i<m;i++) 132 { 133 if(op[i].t) printf("%d\n",dsv[Query(op[i].l,op[i].r,op[i].v)]); 134 else Insert(op[i].l,op[i].r,op[i].v); 135 } 136 137 return 0; 138 }
居然能这么玩..好神......
我们不是要对每个询问在权值线段树上跑嘛...那么位置限制[l,r]怎么办呢? 树套树! 每一个权值线段树的节点都开一棵线段树,用于统计该节点代表的所有权值在某个区间[l,r]内出现过几次.....好神好神.....
动态树
不带其余任何标记的,带换根的LCT.
AC BZOJ2049 一道非常裸的LCT.
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21
22 using namespace std;
23
24 inline int getint()
25 {
26 int res=0;
27 char c=getchar();
28 bool mi=false;
29 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
30 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
31 return mi ? -res : res;
32 }
33 inline ll getll()
34 {
35 ll res=0;
36 char c=getchar();
37 bool mi=false;
38 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
39 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
40 return mi ? -res : res;
41 }
42
43 db eps=1e-18;
44 inline bool feq(db a,db b)
45 { return fabs(a-b)<eps; }
46
47 template<typename Type>
48 inline Type avg(const Type a,const Type b)
49 { return a+((b-a)/2); }
50
51 //==============================================================================
52 //==============================================================================
53 //==============================================================================
54 //==============================================================================
55
56
57
58
59
60 struct node* nil;
61
62 struct node
63 {
64 bool rev;
65 node*s[2],*f;
66
67 bool root()
68 { return this!=f->s[0] && this!=f->s[1]; }
69
70 void pushtag()
71 {
72 if(rev)
73 {
74 s[0]->rev^=1;
75 s[1]->rev^=1;
76 swap(s[0],s[1]);
77 rev=false;
78 }
79 }
80
81 };
82
83
84 struct LinkCutTree
85 {
86 node*nt;
87 LinkCutTree(int size)
88 {
89 nt=new node[size];
90 for(int i=0;i<size;i++)
91 {
92 nt[i].s[0]=nt[i].s[1]=nt[i].f=nil;
93 nt[i].rev=false;
94 }
95 }
96
97 void cleartag(node*x)
98 { if(!x->root()) cleartag(x->f); x->pushtag(); }
99
100 node*operator[](int k)
101 { return nt+k; }
102
103 void rot(node*x)
104 {
105 if(x->root()) return ;
106 node*y=x->f;
107 bool k=(x==y->s[0]);
108
109 y->s[!k]=x->s[k];
110 if(x->s[k]!=nil) x->s[k]->f=y;
111
112 x->f=y->f;
113 if(y==y->f->s[0]) y->f->s[0]=x;
114 else if(y==y->f->s[1]) y->f->s[1]=x;
115
116 y->f=x;
117 x->s[k]=y;
118 }
119
120 void splay(node*x)
121 {
122 cleartag(x);
123 while(!x->root())
124 {
125 node*y=x->f;
126 if(!y->root())
127 {
128 if((x==y->s[0])^(y==y->f->s[0]))
129 rot(y); else rot(x);
130 }
131 rot(x);
132 }
133 }
134
135 node*access(node*x)
136 {
137 node*y=nil;
138 node*t=x;
139 while(t!=nil)
140 {
141 splay(t);
142 t->s[0]=y;
143 y=t;
144 t=t->f;
145 }
146 splay(x);
147 return x;
148 }
149
150 node*FindRoot(node*x)
151 {
152 access(x);
153 while(x->s[1]!=nil) x=x->s[1];
154 return x;
155 }
156
157 node*SetRoot(node*x)
158 {
159 access(x)->rev^=1;
160 return x;
161 }
162
163 void Link(node*x,node*y)
164 {
165 SetRoot(x)->f=y;
166 }
167
168 void Cut(node*x,node*y)
169 {
170 SetRoot(x);
171 access(y);
172 y->s[1]->f=nil;
173 y->s[1]=nil;
174 }
175
176 void output(int i)
177 { cout<<i<<' '<<&nt[i]<<' '<<nt[i].s[0]<<' '<<nt[i].s[1]<<' '<<nt[i].f<<endl; }
178 };
179
180 int n,m;
181
182 int main()
183 {
184 nil=new node;
185 nil->s[0]=nil->s[1]=nil->f=nil;
186
187 n=getint();
188 m=getint();
189
190 LinkCutTree t(n);
191
192 for(int i=0;i<m;i++)
193 {
194 char c[20];
195 scanf("%s",c);
196 if(c[0]=='C') //Link
197 {
198 t.Link(t[getint()-1],t[getint()-1]);
199 }
200 else if(c[0]=='D') //Cut
201 {
202 t.Cut(t[getint()-1],t[getint()-1]);
203 }
204 else if(c[0]=='Q') //Query
205 {
206 if(t.FindRoot(t[getint()-1])==t.FindRoot(t[getint()-1])) printf("Yes\n");
207 else printf("No\n");
208 }
209 }
210
211 return 0;
212 }
很奇怪,Link,Cut,FindRoot和SetRoot这些函数换一种写法就各种TLE/RE,还有cleartag()也是一样,不知道为什么.....
还是LCT.
AC VIJOS1190 LCT-MST
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21
22 using namespace std;
23
24 inline int getint()
25 {
26 int res=0;
27 char c=getchar();
28 bool mi=false;
29 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
30 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
31 return mi ? -res : res;
32 }
33 inline ll getll()
34 {
35 ll res=0;
36 char c=getchar();
37 bool mi=false;
38 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
39 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
40 return mi ? -res : res;
41 }
42
43 db eps=1e-18;
44 inline bool feq(db a,db b)
45 { return fabs(a-b)<eps; }
46
47 template<typename Type>
48 inline Type avg(const Type a,const Type b)
49 { return a+((b-a)/2); }
50
51 //==============================================================================
52 //==============================================================================
53 //==============================================================================
54 //==============================================================================
55
56
57 const int INF=(1<<30)-1;
58
59
60 struct node* nil;
61
62 struct node
63 {
64 node*mxp;
65 int code;
66 int v;
67 bool rev;
68 node*s[2],*f;
69
70 bool root()
71 { return this!=f->s[0] && this!=f->s[1]; }
72
73 void pushtag()
74 {
75 if(rev)
76 {
77 s[0]->rev^=1;
78 s[1]->rev^=1;
79 swap(s[0],s[1]);
80 rev=false;
81 }
82 }
83
84 void update()
85 {
86 mxp=this;
87 int lv=s[0]->mxp->v;
88 int rv=s[1]->mxp->v;
89 if(lv>mxp->v) mxp=s[0]->mxp;
90 if(rv>mxp->v) mxp=s[1]->mxp;
91 }
92 };
93
94
95 struct LinkCutTree
96 {
97 node*nt;
98 LinkCutTree(int size)
99 {
100 nt=new node[size];
101 for(int i=0;i<size;i++)
102 {
103 nt[i].s[0]=nt[i].s[1]=nt[i].f=nil;
104 nt[i].rev=false;
105 nt[i].mxp=&nt[i];
106 nt[i].v=-INF;
107 nt[i].code=i;
108 }
109 }
110
111 void cleartag(node*x)
112 { if(!x->root()) cleartag(x->f); x->pushtag(); }
113
114 node*operator[](int k)
115 { return nt+k; }
116
117 void rot(node*x)
118 {
119 if(x->root()) return ;
120 node*y=x->f;
121 bool k=(x==y->s[0]);
122
123 y->s[!k]=x->s[k];
124 if(x->s[k]!=nil) x->s[k]->f=y;
125
126 x->f=y->f;
127 if(y==y->f->s[0]) y->f->s[0]=x;
128 else if(y==y->f->s[1]) y->f->s[1]=x;
129
130 y->f=x;
131 x->s[k]=y;
132
133 y->update();
134 }
135
136 void splay(node*x)
137 {
138 cleartag(x);
139 while(!x->root())
140 {
141 node*y=x->f;
142 if(!y->root())
143 {
144 if((x==y->s[0])^(y==y->f->s[0]))
145 rot(y); else rot(x);
146 }
147 rot(x);
148 }
149 x->update();
150 }
151
152 node*access(node*x)
153 {
154 node*y=nil;
155 while(x!=nil)
156 {
157 splay(x);
158 x->s[0]=y;
159 y=x;
160 x=x->f;
161 }
162 return x;
163 }
164
165 node*expend(node*x)
166 {
167 access(x);
168 splay(x);
169 return x;
170 }
171
172 node*FindRoot(node*x)
173 {
174 expend(x);
175 while(x->s[1]!=nil) x=x->s[1];
176 splay(x);
177 return x;
178 }
179
180 node*SetRoot(node*x)
181 {
182 expend(x)->rev^=1;
183 return x;
184 }
185
186 void Link(node*x,node*y)
187 {
188 SetRoot(x)->f=y;
189 }
190
191 void Cut(node*x,node*y)
192 {
193 SetRoot(x);
194 expend(y);
195 y->s[1]->f=nil;
196 y->s[1]=nil;
197 }
198
199 node* GetMax(node*x,node*y)
200 {
201 SetRoot(x);
202 return expend(y)->mxp;
203 }
204
205
206 void output(int i)
207 { printf("%p[ id:%d v:%d L:%p R:%p f:%p rev:%d max:%d ]\n",&nt[i],nt[i].code,nt[i].v,nt[i].s[0],nt[i].s[1],nt[i].f,nt[i].rev,nt[i].mxp->v); }
208 };
209
210 int n,m;
211 int EL[10050];
212 int ER[10050];
213
214 int main()
215 {
216 nil=new node;
217 nil->mxp=nil->s[0]=nil->s[1]=nil->f=nil;
218 nil->v=-INF;
219 nil->code=-1;
220
221 n=getint();
222 m=getint();
223
224 LinkCutTree T(n+m+1);
225
226 int mx=-INF;
227
228 for(int i=0;i<m;i++)
229 {
230 int p=n+i;
231
232 int a,b,c;
233 EL[i]=(a=getint()-1);
234 ER[i]=(b=getint()-1);
235 c=getint();
236
237 T[p]->v=c;
238
239 bool able=true;
240
241 if(T.FindRoot(T[a])==T.FindRoot(T[b]))
242 {
243 node* mxp=T.GetMax(T[a],T[b]);
244 able=false;
245
246 if(mxp->v>c)
247 {
248 int d=mxp->code-n;
249
250 T.Cut(T[EL[d]],mxp);
251 T.Cut(T[ER[d]],mxp);
252
253 able=true;
254 }
255 }
256
257 if(able)
258 {
259 T.Link(T[a],T[p]);
260 T.Link(T[b],T[p]);
261 }
262 }
263
264 for(int i=n;i<n+m;i++)
265 if(T.FindRoot(T[0])==T.FindRoot(T[i]))
266 mx=max(mx,T[i]->v);
267
268 printf("%d %d\n",n-1,mx);
269
270 return 0;
271 }
调半天发现update写错了......TAT
要点:
1.所有的操作函数都不要写错啊!虽然很短......
2.access操作返回的是上一次access时的路径与本次access节点在有根树的LCA.
所以用expend函数来作为返回x的access操作.
3.找到根后别忘记splay根上去,毕竟访问了根节点就要保证其复杂度.
4.Cut操作一定要换根,expend(y)之后,把y与y的右儿子断掉.尤其是x,y不一定相邻的时候.
5.update()与pushtag()别写错!
6.在splay前把要splay的节点的父节点的tag清空.因为splay操作是以结构作为基础的.
7.不要在写LCT的时候纠结struct node到底该写哪怎么写的问题!想到怎么写就怎么写,并且LCT函数全部用node*形式.
NOI2014 Day1 T2 魔法森林 用LCT维护MST.上一题就是为这个做准备的.
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21
22 using namespace std;
23
24 inline int getint()
25 {
26 int res=0;
27 char c=getchar();
28 bool mi=false;
29 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
30 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
31 return mi ? -res : res;
32 }
33 inline ll getll()
34 {
35 ll res=0;
36 char c=getchar();
37 bool mi=false;
38 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
39 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
40 return mi ? -res : res;
41 }
42
43 db eps=1e-18;
44 inline bool feq(db a,db b)
45 { return fabs(a-b)<eps; }
46
47 template<typename Type>
48 inline Type avg(const Type a,const Type b)
49 { return a+((b-a)/2); }
50
51 //==============================================================================
52 //==============================================================================
53 //==============================================================================
54 //==============================================================================
55
56
57 const int INF=(1<<30)-1;
58
59
60 struct node* nil;
61
62 struct node
63 {
64 node*mxp;
65 int code;
66 int v;
67 bool rev;
68 node*s[2],*f;
69
70 bool root()
71 { return this!=f->s[0] && this!=f->s[1]; }
72
73 void pushtag()
74 {
75 if(rev)
76 {
77 s[0]->rev^=1;
78 s[1]->rev^=1;
79 swap(s[0],s[1]);
80 rev=false;
81 }
82 }
83
84 void update()
85 {
86 mxp=this;
87 int lv=s[0]->mxp->v;
88 int rv=s[1]->mxp->v;
89 if(lv>mxp->v) mxp=s[0]->mxp;
90 if(rv>mxp->v) mxp=s[1]->mxp;
91 }
92 };
93
94
95 struct LinkCutTree
96 {
97 node*nt;
98 LinkCutTree(int size)
99 {
100 nt=new node[size];
101 for(int i=0;i<size;i++)
102 {
103 nt[i].s[0]=nt[i].s[1]=nt[i].f=nil;
104 nt[i].rev=false;
105 nt[i].mxp=&nt[i];
106 nt[i].v=-INF;
107 nt[i].code=i;
108 }
109 }
110
111 void cleartag(node*x)
112 { if(!x->root()) cleartag(x->f); x->pushtag(); }
113
114 node*operator[](int k)
115 { return nt+k; }
116
117 void rot(node*x)
118 {
119 if(x->root()) return ;
120 node*y=x->f;
121 bool k=(x==y->s[0]);
122
123 y->s[!k]=x->s[k];
124 if(x->s[k]!=nil) x->s[k]->f=y;
125
126 x->f=y->f;
127 if(y==y->f->s[0]) y->f->s[0]=x;
128 else if(y==y->f->s[1]) y->f->s[1]=x;
129
130 y->f=x;
131 x->s[k]=y;
132
133 y->update();
134 }
135
136 void splay(node*x)
137 {
138 cleartag(x);
139 while(!x->root())
140 {
141 node*y=x->f;
142 if(!y->root())
143 {
144 if((x==y->s[0])^(y==y->f->s[0]))
145 rot(y); else rot(x);
146 }
147 rot(x);
148 }
149 x->update();
150 }
151
152 node*access(node*x)
153 {
154 node*y=nil;
155 while(x!=nil)
156 {
157 splay(x);
158 x->s[0]=y;
159 y=x;
160 x=x->f;
161 }
162 return x;
163 }
164
165 node*expend(node*x)
166 {
167 access(x);
168 splay(x);
169 return x;
170 }
171
172 node*FindRoot(node*x)
173 {
174 expend(x);
175 while(x->s[1]!=nil) x=x->s[1];
176 splay(x);
177 return x;
178 }
179
180 node*SetRoot(node*x)
181 {
182 expend(x)->rev^=1;
183 return x;
184 }
185
186 void Link(node*x,node*y)
187 {
188 SetRoot(x)->f=y;
189 }
190
191 void Cut(node*x,node*y)
192 {
193 SetRoot(x);
194 expend(y);
195 y->s[1]->f=nil;
196 y->s[1]=nil;
197 }
198
199 node* GetMax(node*x,node*y)
200 {
201 SetRoot(x);
202 return expend(y)->mxp;
203 }
204
205
206 void output(int i)
207 { printf("%p[ id:%d v:%d L:%p R:%p f:%p rev:%d max:%d ]\n",&nt[i],nt[i].code,nt[i].v,nt[i].s[0],nt[i].s[1],nt[i].f,nt[i].rev,nt[i].mxp->v); }
208 };
209
210 int n,m;
211 int EL[100050];
212 int ER[100050];
213 int Ea[100050];
214 int Eb[100050];
215 int p[100050];
216 bool cmp(int a,int b)
217 { return Ea[a]<Ea[b]; }
218
219 int res=INF;
220
221 int main()
222 {
223 nil=new node;
224 nil->mxp=nil->s[0]=nil->s[1]=nil->f=nil;
225 nil->v=-INF;
226 nil->code=-1;
227
228 n=getint();
229 m=getint();
230
231 LinkCutTree T(n+m+2);
232
233 int st=0,ed=n-1;
234
235 for(int i=0;i<m;i++)
236 {
237 EL[i]=getint()-1;
238 ER[i]=getint()-1;
239 Ea[i]=getint();
240 Eb[i]=getint();
241 }
242
243 for(int i=0;i<m;i++) p[i]=i;
244 stable_sort(p,p+m,cmp);
245
246 int curbase=0;
247
248 for(int i=0;i<m;i++)
249 {
250 int e=p[i]; //the id of current edge.
251 int cur=n+i; //the id of current edge node.
252 node*L=T[EL[e]];
253 node*R=T[ER[e]];
254 curbase=Ea[e]; //current value count.
255 T[cur]->v=Eb[e]; //assign value of current edge node.
256
257 if(L==R) continue;
258
259 if(T.FindRoot(L)==T.FindRoot(R))
260 {
261 node*X=T.GetMax(L,R);
262 int v=X->v;
263
264 if(v>Eb[e]) //replace point mxp
265 {
266 T.Cut(T[EL[X->code-n]],X);
267 T.Cut(T[ER[X->code-n]],X);
268
269 T.Link(L,T[cur]);
270 T.Link(R,T[cur]);
271 }
272 }
273 else
274 {
275 T.Link(L,T[cur]);
276 T.Link(R,T[cur]);
277 }
278
279 if(T.FindRoot(T[n-1])==T.FindRoot(T[0]))
280 {
281 T.SetRoot(T[n-1]);
282 T.expend(T[0]);
283 res=min(res,curbase+T[0]->mxp->v);
284 }
285 }
286
287 if(res==INF) printf("-1\n");
288 else printf("%d\n",res);
289
290 return 0;
291 }
替罪羊树
AC BZOJ 1588
平衡树/权值线段树裸题.
1 #include <cstdio>
2 #include <fstream>
3 #include <iostream>
4
5 #include <cstdlib>
6 #include <cstring>
7 #include <algorithm>
8 #include <cmath>
9
10 #include <queue>
11 #include <vector>
12 #include <map>
13 #include <set>
14 #include <stack>
15 #include <list>
16
17 typedef unsigned int uint;
18 typedef long long int ll;
19 typedef unsigned long long int ull;
20 typedef double db;
21 typedef long double ldb;
22
23 using namespace std;
24
25 inline int getint()
26 {
27 int res=0;
28 char c=getchar();
29 bool mi=false;
30 while((c<'0' || c>'9')&&!feof(stdin)) mi=(c=='-'),c=getchar();
31 while(('0'<=c && c<='9')&&!feof(stdin)) res=res*10+c-'0',c=getchar();
32 return mi ? -res : res;
33 }
34 inline ll getll()
35 {
36 ll res=0;
37 char c=getchar();
38 bool mi=false;
39 while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
40 while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
41 return mi ? -res : res;
42 }
43
44 //==============================================================================
45 //==============================================================================
46 //==============================================================================
47 //==============================================================================
48
49 int f[205000];
50 int s[205000][2];
51 int t[205000];
52 int tot[205000];
53 int ncnt=0;
54
55 int root=0;
56
57 int q[205000]; int qt;
58 void fetch(int x)
59 { if(!x) return ; fetch(s[x][0]); q[qt++]=x; fetch(s[x][1]); }
60 int construct(int l=0,int r=qt-1)
61 {
62 if(l>r) return 0; //nil
63 int mid=(l+r)>>1; int x=q[mid]; tot[x]=1;
64 s[x][0]=construct(l,mid-1); f[s[x][0]]=x; tot[x]+=tot[s[x][0]];
65 s[x][1]=construct(mid+1,r); f[s[x][1]]=x; tot[x]+=tot[s[x][1]];
66 return x;
67 }
68 int rebuild(int x)
69 { qt=0; fetch(x); return construct(); }
70
71 void balance(int x)
72 {
73 int y=0;
74 while(x)
75 {
76 if(tot[x]>=5)
77 {
78 db v=db(tot[s[x][0]])/db(tot[x]-1);
79 if(v<=0.20 || v>=0.80) y=x;
80 }
81 x=f[x];
82 }
83 if(y)
84 {
85 int z=f[y];
86 if(z)
87 {
88 int d=(y==s[z][1]);
89 s[z][d]=rebuild(y);
90 f[s[z][d]]=z;
91 }
92 else root=rebuild(y),f[root]=0;
93 }
94 }
95
96 void Insert(int v)
97 {
98 int p=++ncnt; t[p]=v; tot[p]=1;
99 if(!root) { root=p; return ; }
100 int x=root,y=0;
101 while(x) tot[x]+=1,y=x,x=s[x][v>=t[x]];
102 s[y][v>=t[y]]=p; f[p]=y;
103 balance(p);
104 }
105
106 int Rank(int v)
107 {
108 int x=root,res=0;
109 while(x)
110 if(v<=t[x]) x=s[x][0];
111 else res+=tot[s[x][0]]+1,x=s[x][1];
112 return res;
113 }
114
115 int FindRank(int k)
116 {
117 int x=root,y=0;
118 while(x)
119 {
120 y=x;
121 int c=tot[s[x][0]]+1;
122 if(k==c) break;
123 if(k<c) x=s[x][0];
124 else k-=c,x=s[x][1];
125 }
126 return y;
127 }
128
129 int Prefix(int v) { return t[FindRank(Rank(v))]; }
130 int Suffix(int v) { return t[FindRank(Rank(v)+1)]; }
131
132
133 void op(int x=root)
134 { if(!x)return; op(s[x][0]); printf("%d[v:%d l:%d r:%d f:%d tot:%d]\n",x,t[x],s[x][0],s[x][1],f[x],tot[x]); op(s[x][1]); }
135
136 int n;
137
138 inline int abs(int p){ return p&0x80000000 ? -p : p ; }
139
140 int main()
141 {
142 n=getint();
143
144 int res=getint(); Insert(res);
145 for(int i=1;i<n;i++)
146 {
147 int c=getint();
148 res+=min(abs(c-Prefix(c)),abs(c-Suffix(c)));
149 Insert(c);
150 }
151 printf("%d\n",res);
152
153 return 0;
154 }
参数调成6:0.8/1,加上读入优化,跑了308ms.
不带删除....rank查询前驱后继..........
常数依然降不下来,晚上写一个线段树版本对比一下效率.
...