各种树模板(splay,线段树,可持久化线段树...)
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 }
View Code
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 }
View Code
启发式合并两棵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 }
View Code
线段树
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 }
View Code
区间加,区间求和.永久性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 }
View Code
注意前驱和后继的写法:
想象一下前缀的搜索过程,我们先搜索到询问数字的代表节点,然后回退,如果左子树非空就进入这棵左子树并一直往右往下走.
先写一个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 }
View Code
要点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 }
View Code
所以说啊….我写的可持久化线段树也没那么容易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 }
View Code
好吧,不知怎么的就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 }
View Code
终于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
View Code
需要注意的地方:
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 }
View Code
运行时间为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 }
View Code
加离散化之后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 }
View Code
居然能这么玩..好神……
我们不是要对每个询问在权值线段树上跑嘛…那么位置限制[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 }
View Code
很奇怪,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 }
View Code
调半天发现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 }
View Code
替罪羊树
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 }
View Code
参数调成6:0.8/1,加上读入优化,跑了308ms.
不带删除….rank查询前驱后继……….
常数依然降不下来,晚上写一个线段树版本对比一下效率.
…