各种树模板(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查询前驱后继..........

常数依然降不下来,晚上写一个线段树版本对比一下效率.

 

 

 ...

posted @ 2014-12-27 20:07  DragoonKiller  阅读(1172)  评论(2编辑  收藏  举报