数据结构练习
1、http://www.wikioi.com/problem/1036/
用的是树链剖分写的LCA
1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int maxn=30000; 7 struct xyz111 8 { 9 int tid,size,father,son,top,dep; 10 }tree[maxn+50]; 11 vector<int> g[maxn+50]; 12 int n,m,label=0,q[maxn+50]; 13 void dfs(int k,int father,int dep) 14 { 15 tree[k]={0,1,father,0,0,dep}; 16 int maxsize=0; 17 for(int i=0;i<g[k].size();++i) 18 if(g[k][i]!=father) 19 { 20 dfs(g[k][i],k,dep+1); 21 tree[k].size+=tree[g[k][i]].size; 22 if(tree[g[k][i]].size>maxsize) maxsize=tree[g[k][i]].size,tree[k].son=g[k][i]; 23 } 24 } 25 void connect(int k,int top) 26 { 27 tree[k].tid=++label; 28 tree[k].top=top; 29 if(tree[k].son!=0) connect(tree[k].son,top); 30 for(int i=0;i<g[k].size();++i) 31 if(tree[k].father!=g[k][i]&&tree[k].son!=g[k][i]) connect(g[k][i],g[k][i]); 32 } 33 int question(int x,int y) 34 { 35 int a=x,b=y; 36 while(tree[x].top!=tree[y].top) 37 { 38 if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y); 39 x=tree[tree[x].top].father; 40 } 41 if(tree[x].dep>tree[y].dep) swap(x,y); 42 return tree[a].dep+tree[b].dep-2*tree[x].dep; 43 } 44 int main() 45 { 46 scanf("%d",&n); 47 for(int i=1;i<=n;++i) g[i].clear(); 48 for(int i=1;i<n;++i) 49 { 50 int x,y; 51 scanf("%d %d",&x,&y); 52 g[x].push_back(y); 53 g[y].push_back(x); 54 } 55 scanf("%d",&m); 56 for(int i=1;i<=m;++i) scanf("%d",&q[i]); 57 dfs(1,0,0); 58 connect(1,1); 59 int ans=0; 60 for(int i=2;i<=m;++i) ans+=question(q[i-1],q[i]); 61 printf("%d",ans); 62 return 0; 63 }
2、http://www.wikioi.com/problem/1082/
线段树的Lazy,好久没写线段树,没注意到我的存储方法线段树存储不是满的导致判断溢出的时候BUG了……
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 const long long maxn=200000; 6 struct xyz111 7 { 8 long long l,r,add,sum; 9 }tree[4*maxn]; 10 long long n,q,a[maxn+50]; 11 void push_down(long long k) 12 { 13 tree[k*2].add+=tree[k].add,tree[k*2+1].add+=tree[k].add; 14 tree[k*2].sum+=(tree[k*2].r-tree[k*2].l+1)*tree[k].add,tree[k*2+1].sum+=(tree[k*2+1].r-tree[k*2+1].l+1)*tree[k].add; 15 tree[k].add=0; 16 } 17 void build(long long k,long long l,long long r) 18 { 19 tree[k]={l,r,0,0}; 20 if(l==r) return; 21 long long mid=(l+r)/2; 22 build(k*2,l,mid); 23 build(k*2+1,mid+1,r); 24 } 25 void add(long long k,long long l,long long r,long long x) 26 { 27 if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return; 28 if(tree[k].l>=l&&tree[k].r<=r) 29 { 30 tree[k].add+=x; 31 tree[k].sum+=(tree[k].r-tree[k].l+1)*x; 32 return; 33 } 34 push_down(k); 35 add(k*2,l,r,x); 36 add(k*2+1,l,r,x); 37 tree[k].sum=tree[k*2].sum+tree[k*2+1].sum; 38 } 39 long long ask(long long k,long long l,long long r) 40 { 41 if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return 0; 42 if(tree[k].l>=l&&tree[k].r<=r) return tree[k].sum; 43 push_down(k); 44 return ask(k*2,l,r)+ask(k*2+1,l,r); 45 } 46 int main() 47 { 48 scanf("%d",&n); 49 for(int i=1;i<=4*n;++i) tree[i]={0,0,0,0}; 50 build(1,1,n); 51 for(int i=1;i<=n;++i) scanf("%lld",&a[i]); 52 for(int i=1;i<=n;++i) add(1,i,i,a[i]); 53 scanf("%d",&q); 54 for(int i=1;i<=q;++i) 55 { 56 long long l,x,y,z; 57 scanf("%lld",&l); 58 if(l==1) 59 { 60 scanf("%lld %lld %lld",&x,&y,&z); 61 add(1,x,y,z); 62 } 63 else 64 { 65 scanf("%lld %lld",&x,&y); 66 printf("%lld\n",ask(1,x,y)); 67 } 68 } 69 return 0; 70 }
3、http://www.wikioi.com/problem/1191/
简单的线段树lazy
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 const int maxn=200000; 6 struct xyz111 7 { 8 int l,r,v,sum; 9 }tree[maxn*4]; 10 int n,m; 11 void build(int k,int l,int r) 12 { 13 tree[k]={l,r,0,0}; 14 if(l==r) return; 15 int mid=(l+r)/2; 16 build(k*2,l,mid); 17 build(k*2+1,mid+1,r); 18 } 19 void push_down(int k) 20 { 21 if(tree[k].v==0) return; 22 tree[k*2].v=1,tree[k*2].sum=tree[k*2].r-tree[k*2].l+1; 23 tree[k*2+1].v=1,tree[k*2+1].sum=tree[k*2+1].r-tree[k*2+1].l+1; 24 tree[k].v=0; 25 } 26 void update(int k,int l,int r) 27 { 28 if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return; 29 if(tree[k].l>=l&&tree[k].r<=r) 30 { 31 tree[k].sum=tree[k].r-tree[k].l+1; 32 tree[k].v=1; 33 return; 34 } 35 push_down(k); 36 update(k*2,l,r); 37 update(k*2+1,l,r); 38 tree[k].sum=tree[k*2].sum+tree[k*2+1].sum; 39 } 40 int ask(int k,int l,int r) 41 { 42 if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return 0; 43 if(tree[k].l>=l&&tree[k].r<=r) return tree[k].sum; 44 push_down(k); 45 return ask(k*2,l,r)+ask(k*2+1,l,r); 46 } 47 int main() 48 { 49 scanf("%d %d",&n,&m); 50 for(int i=1;i<=4*n;++i) tree[i]={0,0,0}; 51 build(1,1,n); 52 for(int i=1;i<=m;++i) 53 { 54 int x,y; 55 scanf("%d %d",&x,&y); 56 update(1,x,y); 57 printf("%d\n",n-ask(1,1,n)); 58 } 59 return 0; 60 }
4、http://www.wikioi.com/problem/1299/
上一题的加强版,数据范围变大了,卡线段树,正解是并查集,在模拟的基础上,将每个点的祖先定为右边的最近的没被染色的点,所以每次染色一个区间就可以很快了
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 const int maxn=2000000; 6 int f[maxn+50],n,m; 7 long long find(long long x) 8 { 9 if(f[x]==x) return x; 10 return f[x]=find(f[x]); 11 } 12 int main() 13 { 14 scanf("%d %d",&n,&m); 15 for(int i=1;i<=n;++i) f[i]=i; 16 int ans=n; 17 for(int i=1;i<=m;++i) 18 { 19 int x,y; 20 scanf("%d %d",&x,&y); 21 x=find(x); 22 while(x<=y) 23 { 24 --ans; 25 f[x]=x+1; 26 x=find(x); 27 } 28 printf("%d\n",ans); 29 } 30 return 0; 31 }
5、http://www.wikioi.com/problem/1286/
经典的平衡树题,这个是用Treap写的
1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<ctime> 5 using namespace std; 6 const int maxn=100000,inf=1e9; 7 struct xyz111 8 { 9 xyz111* ch[2]; 10 int size,value,key,num; 11 int cmp(int x) 12 { 13 if(x==value) return -1; 14 return value<x; 15 } 16 void maintain() 17 { 18 size=num; 19 if(ch[0]!=NULL) size+=ch[0]->size; 20 if(ch[1]!=NULL) size+=ch[1]->size; 21 } 22 }; 23 xyz111* root=NULL; 24 int n,m,s=0; 25 void rorate(xyz111* &o,int d) 26 { 27 xyz111* k=o->ch[d^1]; 28 o->ch[d^1]=k->ch[d]; 29 k->ch[d]=o; 30 o->maintain(); 31 k->maintain(); 32 o=k; 33 } 34 void insert(xyz111* &o,int x) 35 { 36 if(o==NULL) 37 { 38 o=new xyz111(); 39 o->ch[0]=o->ch[1]=NULL; 40 o->size=1; 41 o->value=x; 42 o->key=rand()%inf; 43 o->num=1; 44 } 45 else 46 { 47 int d=o->cmp(x); 48 if(d==-1) ++o->num; 49 else 50 { 51 insert(o->ch[d],x); 52 if(o->ch[d]->key>o->key) rorate(o,d^1); 53 } 54 } 55 o->maintain(); 56 } 57 void dfs(xyz111* &o,int x) 58 { 59 if(o==NULL) return; 60 int d=o->cmp(x); 61 if(d==0||d==-1) dfs(o->ch[0],x); 62 if(d==1) 63 { 64 if(o->ch[1]!=NULL) o=o->ch[1];else o=NULL; 65 dfs(o,x); 66 } 67 if(o!=NULL)o->maintain(); 68 } 69 int kth(xyz111* o,int k) 70 { 71 int l=0; 72 if(o->ch[0]!=NULL) l=o->ch[0]->size; 73 if(l<k&&l+o->num>=k) return o->value; 74 if(l+o->num<k) return kth(o->ch[1],k-l-o->num); 75 return kth(o->ch[0],k); 76 } 77 int main() 78 { 79 srand(time(0)); 80 scanf("%d %d\n",&n,&m); 81 int b=0; 82 for(int i=1;i<=n;++i) 83 { 84 char c; 85 int x; 86 scanf("%c %d\n",&c,&x); 87 if(c=='I') 88 { 89 if(x<m) continue; 90 insert(root,x-s); 91 ++b; 92 } 93 if(c=='A') s+=x; 94 if(c=='S') 95 { 96 s-=x; 97 dfs(root,m-s); 98 } 99 if(c=='F') if(root==NULL||x>root->size) printf("-1\n");else printf("%d\n",kth(root,root->size-x+1)+s); 100 } 101 if(root==NULL) printf("%d",b);else printf("%d",b-root->size); 102 return 0; 103 }
6、http://www.wikioi.com/problem/1296/
平衡树撸,用Treap的……
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<ctime> 5 using namespace std; 6 const int maxn=32767; 7 struct xyz111 8 { 9 xyz111* ch[2]; 10 int value,key,size; 11 int cmp(int x) 12 { 13 if(value==x) return -1; 14 return value<x; 15 } 16 void maintain() 17 { 18 size=1; 19 if(ch[0]!=NULL) size+=ch[0]->size; 20 if(ch[1]!=NULL) size+=ch[1]->size; 21 } 22 }; 23 xyz111* root=NULL; 24 int n; 25 void rorate(xyz111* &o,int d) 26 { 27 xyz111* k=o->ch[d^1]; 28 o->ch[d^1]=k->ch[d]; 29 k->ch[d]=o; 30 o->maintain(); 31 k->maintain(); 32 o=k; 33 } 34 void insert(xyz111* &o,int x) 35 { 36 if(o==NULL) 37 { 38 o=new xyz111(); 39 o->ch[0]=o->ch[1]=NULL; 40 o->value=x; 41 o->size=1; 42 o->key=rand()%100000000; 43 } 44 else 45 { 46 int d=o->cmp(x); 47 if(d==-1) return; 48 insert(o->ch[d],x); 49 if(o->ch[d]->key>o->key) rorate(o,d^1); 50 } 51 o->maintain(); 52 } 53 int kth(xyz111* o,int k) 54 { 55 int l=0; 56 if(o->ch[0]!=NULL) l=o->ch[0]->size; 57 if(l+1==k) return o->value; 58 if(l+1>k) return kth(o->ch[0],k); 59 return kth(o->ch[1],k-l-1); 60 } 61 int rank(xyz111* o,int x) 62 { 63 if(o==NULL) return 0; 64 int d=o->cmp(x),l=0; 65 if(o->ch[0]!=NULL) l=o->ch[0]->size; 66 if(d==-1) return l+1; 67 if(d==0) return rank(o->ch[0],x); 68 return l+1+rank(o->ch[1],x); 69 } 70 int main() 71 { 72 scanf("%d",&n); 73 int ans; 74 scanf("%d",&ans); 75 insert(root,ans); 76 for(int i=2;i<=n;++i) 77 { 78 int x; 79 scanf("%d",&x); 80 int k=rank(root,x); 81 if(k==0) ans+=kth(root,1)-x; 82 else 83 if(k==root->size) ans+=x-kth(root,root->size); 84 else 85 ans+=min(x-kth(root,k),kth(root,k+1)-x); 86 insert(root,x); 87 } 88 printf("%d",ans); 89 return 0; 90 }
7、http://www.lydsy.com/JudgeOnline/problem.php?id=1798
线段树成段更新,有乘法和加法
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 const int maxn=100000; 6 struct xyz111 7 { 8 int l,r; 9 long long add,mult,sum; 10 }tree[4*maxn+50]; 11 int n,p,m; 12 void build(int k,int l,int r) 13 { 14 tree[k].l=l,tree[k].r=r,tree[k].add=0,tree[k].mult=1; 15 if(l==r) scanf("%d",&tree[k].sum); 16 else 17 { 18 int mid=(l+r)/2; 19 build(k*2,l,mid); 20 build(k*2+1,mid+1,r); 21 tree[k].sum=tree[k*2].sum+tree[k*2+1].sum; 22 } 23 } 24 void maintain(int k,long long add,long long mult) 25 { 26 if(tree[k].l==0&&tree[k].r==0) return; 27 tree[k].mult=(tree[k].mult*mult)%p; 28 tree[k].add=((tree[k].add*mult)%p+add)%p; 29 tree[k].sum=((tree[k].sum+(tree[k].sum*(mult-1))%p)%p+(add*(tree[k].r-tree[k].l+1))%p)%p; 30 } 31 void updata(int k,int l,int r,long long add,long long mult) 32 { 33 if(tree[k].l>r||tree[k].r<l||(tree[k].l==0&&tree[k].r==0)) return; 34 if(tree[k].l>=l&&tree[k].r<=r) maintain(k,add,mult); 35 else 36 { 37 int mid=(tree[k].l+tree[k].r)/2; 38 maintain(k*2,tree[k].add,tree[k].mult); 39 maintain(k*2+1,tree[k].add,tree[k].mult); 40 tree[k].mult=1,tree[k].add=0; 41 updata(k*2,l,r,add,mult); 42 updata(k*2+1,l,r,add,mult); 43 tree[k].sum=(tree[k*2].sum+tree[k*2+1].sum)%p; 44 } 45 } 46 int ask(int k,int l,int r) 47 { 48 if(tree[k].l>r||tree[k].r<l||(tree[k].l==0&&tree[k].r==0)) return 0; 49 if(tree[k].l>=l&&tree[k].r<=r) return tree[k].sum; 50 int mid=(tree[k].l+tree[k].r)/2; 51 maintain(k*2,tree[k].add,tree[k].mult); 52 maintain(k*2+1,tree[k].add,tree[k].mult); 53 tree[k].mult=1,tree[k].add=0; 54 return (ask(k*2,l,r)+ask(k*2+1,l,r))%p; 55 } 56 int main() 57 { 58 scanf("%d %d",&n,&p); 59 for(int k=1;k<=4*n;++k) tree[k].l=tree[k].r=0,tree[k].add=0,tree[k].mult=1,tree[k].sum=0; 60 build(1,1,n); 61 int k=1; 62 scanf("%d",&m); 63 for(int i=1;i<=m;++i) 64 { 65 int a,b,c,d; 66 scanf("%d",&a); 67 if(a==3) 68 { 69 scanf("%d %d",&b,&c); 70 printf("%d\n",ask(1,b,c)); 71 continue; 72 } 73 scanf("%d %d %d",&b,&c,&d); 74 if(a==1) updata(1,b,c,0,d);else updata(1,b,c,d,1); 75 } 76 k=1; 77 return 0; 78 }
8、http://codevs.cn/problem/3303/
splay维护数列的简单问题
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 const int maxn=100000; 6 int pre[maxn+50],ch[maxn+50][2],flip[maxn+50],key[maxn+50],size[maxn+50]; 7 int n,m,root=0,len=0; 8 void update(int k) 9 { 10 size[k]=size[ch[k][0]]+size[ch[k][1]]+1; 11 } 12 void pushdown(int k) 13 { 14 if(flip[k]==0) return; 15 flip[k]=0; 16 swap(ch[k][0],ch[k][1]); 17 flip[ch[k][0]]^=1; 18 flip[ch[k][1]]^=1; 19 } 20 void rorate(int k,int d) 21 { 22 int f=pre[pre[k]],p=pre[k]; 23 pushdown(p),pushdown(k); 24 ch[p][d^1]=ch[k][d]; 25 pre[ch[k][d]]=p; 26 ch[k][d]=p; 27 pre[k]=f; 28 pre[p]=k; 29 if(f) ch[f][ch[f][1]==p]=k;else root=k; 30 update(p),update(k); 31 } 32 void splay(int x,int goal) 33 { 34 while(pre[x]!=goal) 35 { 36 pushdown(x); 37 if(pre[pre[x]]==goal) rorate(x,ch[pre[x]][0]==x); 38 else 39 { 40 int d1=ch[pre[x]][0]==x,d2=ch[pre[pre[x]]][0]==pre[x]; 41 if(d1==d2) rorate(pre[x],d2),rorate(x,d1); 42 else rorate(x,d1),rorate(x,d2); 43 } 44 } 45 update(x); 46 if(goal==0) root=x; 47 } 48 void insert(int v) 49 { 50 int k=root; 51 while(ch[k][1]!=0) k=ch[k][1]; 52 ++len; 53 pre[len]=k,ch[len][0]=ch[len][1]=0,flip[len]=0,key[len]=v,size[len]=1,ch[k][1]=len; 54 if(root==0) root=k; 55 splay(len,0); 56 } 57 void find(int k,int goal) 58 { 59 int t=root; 60 while(true) 61 { 62 pushdown(t); 63 if(size[ch[t][0]]+1==k) break; 64 if(k<=size[ch[t][0]]) t=ch[t][0];else k-=size[ch[t][0]]+1,t=ch[t][1]; 65 } 66 splay(t,goal); 67 } 68 void ask(int k) 69 { 70 if(k==0) return; 71 pushdown(k); 72 ask(ch[k][0]); 73 if(key[k]>=2&&key[k]<=n+1)printf("%d ",key[k]-1); 74 ask(ch[k][1]); 75 } 76 int main() 77 { 78 scanf("%d %d",&n,&m); 79 for(int i=1;i<=n+2;++i) insert(i); 80 splay((n+2)/2,0); 81 for(int i=1;i<=m;++i) 82 { 83 int x,y; 84 scanf("%d %d",&x,&y); 85 x+=1,y+=1; 86 find(x-1,0); 87 find(y+1,root); 88 flip[ch[ch[root][1]][0]]^=1; 89 } 90 ask(root); 91 return 0; 92 }
9、http://www.lydsy.com:808/JudgeOnline/problem.php?id=2002
link-cut tree模板
1 #include<cstring> 2 #include<algorithm> 3 #include<vector> 4 #include<cstdio> 5 using namespace std; 6 const int maxn=200000; 7 bool root[maxn+50];//root[i]表示节点i是否为它所在辅助树的根 8 int father[maxn+50],size[maxn+50],ch[maxn+50][2]; 9 //father[i]记录i的父亲,他的父亲可能跟i在一个辅助树上也可能不在;size[i]表示在i所在的辅助树中以i为子树的节点个数;ch[i][0..1]记录的是i在辅助树中的左儿子和右儿子,如果没有用0表示 10 int n,m; 11 void update(int k) 12 { 13 if(k==0) return; 14 size[k]=size[ch[k][0]]+size[ch[k][1]]+1; 15 } 16 void rorate(int k,int d) 17 { 18 int p=father[k],f=father[father[k]]; 19 ch[p][d^1]=ch[k][d]; 20 father[ch[k][d]]=p; 21 ch[k][d]=p; 22 father[p]=k; 23 father[k]=f; 24 if(f) 25 if(ch[f][0]==p) ch[f][0]=k;else if(ch[f][1]==p) ch[f][1]=k;//此处一定要注意,因为可能f和k不在一个辅助树上 26 update(p); 27 update(k); 28 if(root[p]) root[k]=1,root[p]=0;//root[p]=0一定要记得加上 29 } 30 void splay(int k) 31 { 32 while (!root[k]) 33 { 34 if(root[father[k]]) rorate(k,ch[father[k]][0]==k); 35 else 36 { 37 int d1=ch[father[k]][0]==k,d2=ch[father[father[k]]][0]==father[k]; 38 if(d1==d2) rorate(father[k],d2),rorate(k,d1);else rorate(k,d1),rorate(k,d2); 39 } 40 } 41 update(k); 42 } 43 void access(int x) 44 { 45 splay(x); 46 while(father[x]) 47 { 48 int y=father[x]; 49 splay(y); 50 root[ch[y][1]]=1; 51 root[x]=0; 52 ch[y][1]=x; 53 update(y); 54 splay(x); 55 } 56 } 57 void cut(int x) 58 { 59 access(x); 60 splay(x); 61 father[ch[x][0]]=0; 62 root[ch[x][0]]=1; 63 ch[x][0]=0; 64 update(x); 65 } 66 void link(int x,int y) 67 { 68 if(y>n) y=n+1; 69 father[x]=y; 70 } 71 int main() 72 { 73 freopen("ce.in","r",stdin); 74 freopen("ce.out","w",stdout); 75 scanf("%d",&n); 76 for(int i=1;i<=n;++i) 77 { 78 scanf("%d",&father[i]); 79 father[i]+=i; 80 if(father[i]>n) father[i]=n+1; 81 } 82 scanf("%d",&m); 83 memset(size,0,sizeof(size)); 84 for(int i=1;i<=n+1;++i) size[i]=1; 85 memset(root,1,sizeof(root)); 86 memset(ch,0,sizeof(ch)); 87 for(int i=1;i<=m;++i) 88 { 89 int x,y,z; 90 scanf("%d %d",&x,&y); 91 ++y; 92 if(x==1) 93 { 94 access(y); 95 printf("%d\n",size[ch[y][0]]); 96 } 97 else 98 { 99 scanf("%d",&z); 100 cut(y); 101 link(y,y+z); 102 } 103 } 104 return 0; 105 } 106
10、还是上一题
分块模板
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<vector> 5 #include<cmath> 6 using namespace std; 7 const int maxn=200000; 8 int k[maxn+50],block[maxn+50],next[maxn+50],step[maxn+50]; 9 int n,m,l; 10 //block[i]计数i所处的块的编号;next[i]表示i一直往后跳直到跳出当前块的位置;step[i]表示i到next[i]要跳几步 11 void build(int l,int r) 12 { 13 for(int i=r;i>=l;--i) 14 if(i+k[i]>n) next[i]=0,step[i]=1; 15 else 16 if(block[i]==block[i+k[i]]) next[i]=next[i+k[i]],step[i]=step[i+k[i]]+1; 17 else next[i]=i+k[i],step[i]=1; 18 }//build(l,r)表示把[l,r]这一段重新维护一下 19 void ask(int x) 20 { 21 int s=0; 22 while(x) 23 { 24 s+=step[x]; 25 x=next[x]; 26 } 27 printf("%d\n",s); 28 } 29 int main() 30 { 31 freopen("ce.in","r",stdin); 32 freopen("ce.out","w",stdout); 33 scanf("%d",&n); 34 l=int(sqrt(n)); 35 for(int i=1;i<=n;++i) scanf("%d",&k[i]),block[i]=(i-1)/l+1; 36 build(1,n); 37 scanf("%d",&m); 38 for(int i=1;i<=m;++i) 39 { 40 int x,y,z; 41 scanf("%d %d",&x,&y); 42 ++y; 43 if(x==1) ask(y);else scanf("%d",&z),k[y]=z,build(l*(block[y]-1)+1,y); 44 } 45 return 0; 46 }
11、http://www.lydsy.com:808/JudgeOnline/problem.php?id=1036
树链剖分模板
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<vector> 5 using namespace std; 6 const int maxn=30000,inf=1e9; 7 struct wjmzbmr 8 { 9 int tid,top,size,son,dep,father,v; 10 }tree[maxn+50]; 11 struct fotile96 12 { 13 int maxnum,sum; 14 }f[4*maxn+50]; 15 vector<int> g[maxn+50]; 16 int pos[maxn+50]; 17 int n,label=0,q; 18 void dfs(int x,int fa,int dep) 19 { 20 tree[x]=(wjmzbmr){0,0,1,0,dep,fa,tree[x].v}; 21 int m=0; 22 for(int i=0;i<g[x].size();++i) 23 if(g[x][i]!=fa) 24 { 25 dfs(g[x][i],x,dep+1); 26 tree[x].size+=tree[g[x][i]].size; 27 if(tree[g[x][i]].size>m) m=tree[g[x][i]].size,tree[x].son=g[x][i]; 28 } 29 } 30 void connect(int x,int top) 31 { 32 tree[x].tid=++label,pos[tree[x].tid]=x; 33 tree[x].top=top; 34 if(tree[x].son!=0) connect(tree[x].son,top); 35 for(int i=0;i<g[x].size();++i) 36 if(g[x][i]!=tree[x].father&&g[x][i]!=tree[x].son) connect(g[x][i],g[x][i]); 37 } 38 void make(int k,int l,int r) 39 { 40 if(l>r) return; 41 if(l==r) f[k].maxnum=f[k].sum=tree[pos[l]].v; 42 else 43 { 44 int mid=(l+r)>>1; 45 make(k*2,l,mid); 46 make(k*2+1,mid+1,r); 47 f[k].sum=f[k*2].sum+f[k*2+1].sum; 48 f[k].maxnum=max(f[k*2].maxnum,f[k*2+1].maxnum); 49 } 50 } 51 void change(int k,int l,int r,int x,int y) 52 { 53 if(l>r||r<x||l>x) return; 54 if(l==r) 55 { 56 if(l==x) f[k].maxnum=y,f[k].sum=y; 57 return; 58 } 59 int mid=(l+r)>>1; 60 change(k*2,l,mid,x,y); 61 change(k*2+1,mid+1,r,x,y); 62 f[k].sum=f[k*2].sum+f[k*2+1].sum; 63 f[k].maxnum=max(f[k*2].maxnum,f[k*2+1].maxnum); 64 } 65 int qqmax(int k,int l,int r,int ll,int rr) 66 { 67 if(l>r||l>rr||r<ll) return -inf; 68 if(l>=ll&&r<=rr) return f[k].maxnum; 69 int mid=(l+r)>>1; 70 return max(qqmax(k*2,l,mid,ll,rr),qqmax(k*2+1,mid+1,r,ll,rr)); 71 } 72 int qmax(int x,int y) 73 { 74 int ans=-inf; 75 while(tree[x].top!=tree[y].top) 76 { 77 if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y); 78 ans=max(ans,qqmax(1,1,n,tree[tree[x].top].tid,tree[x].tid)); 79 x=tree[tree[x].top].father; 80 } 81 if(tree[x].dep>tree[y].dep) swap(x,y); 82 ans=max(ans,qqmax(1,1,n,tree[x].tid,tree[y].tid)); 83 return ans; 84 } 85 int qqsum(int k,int l,int r,int ll,int rr) 86 { 87 if(l>r||l>rr||r<ll) return 0; 88 if(l>=ll&&r<=rr) return f[k].sum; 89 int mid=(l+r)>>1; 90 return qqsum(k*2,l,mid,ll,rr)+qqsum(k*2+1,mid+1,r,ll,rr); 91 } 92 int qsum(int x,int y) 93 { 94 int ans=0; 95 while(tree[x].top!=tree[y].top) 96 { 97 if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y); 98 ans+=qqsum(1,1,n,tree[tree[x].top].tid,tree[x].tid); 99 x=tree[tree[x].top].father; 100 } 101 if(tree[x].dep>tree[y].dep) swap(x,y); 102 ans+=qqsum(1,1,n,tree[x].tid,tree[y].tid); 103 return ans; 104 } 105 int main() 106 { 107 freopen("ce.in","r",stdin); 108 freopen("ce.out","w",stdout); 109 scanf("%d",&n); 110 for(int i=1;i<=n;++i) g[i].clear(); 111 for(int i=1;i<n;++i) 112 { 113 int x,y; 114 scanf("%d %d",&x,&y); 115 g[x].push_back(y); 116 g[y].push_back(x); 117 } 118 for(int i=1;i<=n;++i) scanf("%d",&tree[i].v); 119 dfs(1,0,0); 120 connect(1,1); 121 make(1,1,n); 122 scanf("%d\n",&q); 123 for(int i=1;i<=q;++i) 124 { 125 int x,y; 126 char s[10]; 127 scanf("%s %d %d\n",s,&x,&y); 128 if(s[0]=='C') change(1,1,n,tree[x].tid,y); 129 if(s[1]=='M') printf("%d\n",qmax(x,y)); 130 if(s[1]=='S') printf("%d\n",qsum(x,y)); 131 } 132 return 0; 133 }
12、SAP模版
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<vector> 5 using namespace std; 6 const int maxn=20000,inf=1e8; 7 struct wjmzbmr 8 { 9 int from,to,flow; 10 }E[maxn+50]; 11 vector<int> g[maxn+50]; 12 int n,m,len=-1; 13 int d[maxn+50,dv[maxn+50]; 14 int dfs(int k,int flow) 15 { 16 if(k==n) return flow; 17 int f=0; 18 for(int i=0;i<g[k].size();++i) 19 { 20 wjmzbmr e=E[g[k][i]]; 21 int k=dfs(e.to,min(flow-f,e.flow)); 22 e.flow-=k; 23 E[g[k][i]^1].flow+=k; 24 f+=k; 25 if(f==flow) return f; 26 } 27 if(d[1]==n) return f; 28 --dv[d[k]]; 29 if(dv[d[k]]==0) d[1]=n; 30 ++d[k]; 31 ++dv[d[k]]; 32 } 33 int main() 34 { 35 freopen("ce.in","r",stdin); 36 scanf("%d %d",&n,&m); 37 for(int i=1;i<=m;++i) 38 { 39 int a,b,c; 40 scanf("%d %d %d",&a,&b,&c); 41 ++len; 42 e[len]=(wjmzbmr){a,b,c}; 43 g[a].push_back(len); 44 ++len; 45 e[len]=(wjmzbmr){b,a,0}; 46 g[b].push_back(len); 47 } 48 for(int i=1;i<=n;++i) d[i]=n; 49 memset(dv,0,sizeof(dv)); 50 dv[1]=n; 51 int ans=0; 52 while (d[1]<n) 53 { 54 ans+=dfs(1,inf); 55 } 56 return 0; 57 }
(未完待续)