BZOJ2157: 旅游 树链剖分 线段树

Posted 鲸头鹳

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2157: 旅游 树链剖分 线段树相关的知识,希望对你有一定的参考价值。

 
在对树中数据进行改动的时候需要很多pushdown(具体操作见代码),不然会wa,大概原因和线段树区间修改需要很多pushup是一样的。
这个轻重链的方法特别好用,虽然第一次写树链剖分但是容易理解又有优秀复杂度的结构让人情不自禁orz。
(后来发现很久以前学lca的时候就学了树链剖分只不过忘了,mdzz)
因为忘了去掉测试代码的freopen,re了4次(虽然有三次就算不re也wa),发现一行一行检查对于数据结构的调试很有用(虽然一直找不出来re原因但是我起码避免了很多wa呀)。
 
代码
技术分享
  1 #include<iostream>  
  2 #include<cstdio>  
  3 #include<cstring>  
  4 #include<algorithm>  
  5 #include<cmath>  
  6 using namespace std;
  7 const int maxn=20100;
  8 const long long modn=1000000007;
  9 const int minf=1<<30;
 10 int n,m;char ch[5]={};
 11 struct nod{
 12     int y,next,v;
 13 }e[maxn*2];
 14 int head[maxn]={},tot=0;
 15 struct seg{
 16     int mi,mx,sum,c,l,r;
 17     int f,rev;
 18     seg(){mi=mx=sum=c=l=r=0;f=rev=0;}
 19 }t[maxn*4];
 20 int dep[maxn]={},crs[maxn]={},pos[maxn]={},road[maxn]={};
 21 int kid[maxn]={},fa[maxn]={},top[maxn]={};
 22 void init(int x,int y,int v){
 23     e[++tot].v=v;e[tot].y=y;
 24     e[tot].next=head[x];head[x]=tot;
 25 }
 26 int dfs1(int x,int pa){
 27     int y,siz=0,tsn=1,ma=0;
 28     fa[x]=pa;dep[x]=dep[pa]+1;
 29     for(int i=head[x];i;i=e[i].next){
 30         y=e[i].y;
 31         if(y==pa)continue;
 32         siz=dfs1(y,x);tsn+=siz;
 33         if(siz>ma)ma=siz,kid[x]=y;
 34         crs[(i+1)/2]=y;
 35     }
 36     return tsn;
 37 }
 38 void dfs2(int x,int pa){
 39     int y,v;
 40     pos[x]=++tot;top[x]=pa;
 41     if(kid[x])dfs2(kid[x],pa);
 42     for(int i=head[x];i;i=e[i].next){
 43         y=e[i].y;v=e[i].v;
 44         if(y==kid[x])road[pos[kid[x]]]=v;
 45         if(y==kid[x]||y==fa[x])continue;
 46         road[tot+1]=v;
 47         dfs2(y,y);
 48     }
 49 }
 50 void pushup(int x){
 51     int l=x*2,r=x*2+1;
 52     t[x].mx=max(t[l].mx,t[r].mx);
 53     t[x].mi=min(t[l].mi,t[r].mi);
 54     t[x].sum=t[l].sum+t[r].sum;
 55 }
 56 void pushdown(int x){
 57     if(t[x].f){
 58         int l=x*2,r=x*2+1;
 59         t[x].rev=t[x].f=0;
 60         t[x].mx=t[x].mi=t[x].c;
 61         t[x].sum=t[x].c*(t[x].r-t[x].l+1);
 62         if(t[x].l<t[x].r){
 63             t[l].c=t[r].c=t[x].c;
 64             t[l].f=t[r].f=1;
 65             t[l].rev=t[r].rev=0;
 66         }
 67         return;
 68     }
 69     if(t[x].rev){
 70         int l=x*2,r=x*2+1;
 71         t[x].rev=0;
 72         swap(t[x].mi,t[x].mx);
 73         t[x].mx*=-1;t[x].mi*=-1;t[x].sum*=-1;
 74         if(t[x].l<t[x].r){
 75             t[l].c*=-1;t[l].rev^=1;
 76             t[r].c*=-1;t[r].rev^=1;
 77         }
 78     }
 79 }
 80 void build(int x,int l,int r){
 81     t[x].l=l,t[x].r=r;
 82     if(l==r){
 83         t[x].mx=t[x].mi=t[x].sum=road[l];
 84         return;
 85     }
 86     int mid=(l+r)/2;
 87     build(x*2,l,mid);
 88     build(x*2+1,mid+1,r);
 89     pushup(x);
 90 }
 91 void cov(int x,int l,int r,int w){
 92     if(t[x].l>=l&&t[x].r<=r){
 93         t[x].f=1;t[x].c=w; pushdown(x);
 94         return;
 95     }
 96     pushdown(x);
 97     int mid=(t[x].l+t[x].r)/2;
 98     if(l<=mid)cov(x*2,l,r,w);
 99     pushdown(x*2);
100     if(r>mid) cov(x*2+1,l,r,w);
101     pushdown(x*2+1);
102     pushup(x);
103 }
104 void revs(int x,int l,int r){
105     if(t[x].l>=l&&t[x].r<=r){
106         t[x].c*=-1;t[x].rev^=1;
107         pushdown(x);
108         return;
109     }pushdown(x);
110     int mid=(t[x].l+t[x].r)/2;
111     if(l<=mid) revs(x*2,l,r);
112     pushdown(x*2);
113     if(r>mid) revs(x*2+1,l,r);
114     pushdown(x*2+1);
115     pushup(x);
116 }
117 int mi(int x,int l,int r){
118     pushdown(x);
119     if(t[x].l>=l&&t[x].r<=r){
120         return t[x].mi;
121     }
122     int mid=(t[x].l+t[x].r)/2,minn=minf;
123     if(l<=mid) minn=min(minn,mi(x*2,l,r));
124     if(r>mid) minn=min(minn,mi(x*2+1,l,r));
125     return minn;
126 }
127 int mx(int x,int l,int r){
128     pushdown(x);
129     if(t[x].l>=l&&t[x].r<=r){
130         return t[x].mx;
131     }
132     int mid=(t[x].l+t[x].r)/2,mxn=-minf;
133     if(l<=mid) mxn=max(mxn,mx(x*2,l,r));
134     if(r>mid) mxn=max(mxn,mx(x*2+1,l,r));
135     return mxn;
136 }
137 int su(int x,int l,int r){
138     pushdown(x);
139     if(t[x].l>=l&&t[x].r<=r){
140         return t[x].sum;
141     }
142     int mid=(t[x].l+t[x].r)/2,sumn=0;
143     if(l<=mid) sumn+=su(x*2,l,r);
144     if(r>mid) sumn+=su(x*2+1,l,r);
145     return sumn;
146 }
147 void mrev(int x,int y){
148     int a,b;
149     for(a=top[x],b=top[y];a!=b;){
150         if(dep[a]<dep[b])swap(a,b),swap(x,y);
151         revs(1,pos[a],pos[x]);
152         x=fa[a];a=top[x];
153     }
154     if(dep[x]>dep[y])swap(x,y);
155     if(x!=y) revs(1,pos[x]+1,pos[y]);
156 }
157 void doit(int x,int y,int k){
158     int a,b,mxn=-minf,minn=minf,sumn=0;
159     for(a=top[x],b=top[y];a!=b;){
160         if(dep[a]<dep[b])swap(a,b),swap(x,y);
161         if(k==0) sumn+=su(1,pos[a],pos[x]);
162         else if(k==1) mxn=max(mx(1,pos[a],pos[x]),mxn);
163         else minn=min(mi(1,pos[a],pos[x]),minn);
164         x=fa[a];a=top[x];
165     }
166     if(dep[x]>dep[y])swap(x,y);
167     if(x!=y){
168         if(k==0) sumn+=su(1,pos[x]+1,pos[y]);
169         else if(k==1) mxn=max(mx(1,pos[x]+1,pos[y]),mxn);
170         else minn=min(mi(1,pos[x]+1,pos[y]),minn);
171     }
172     if(k==0) printf("%d\n",sumn);
173     else if(k==1) printf("%d\n",mxn);
174     else printf("%d\n",minn);
175 }
176 int main(){
177     //freopen("wtf.in","r",stdin);
178     //freopen("wtf.out","w",stdout);
179     scanf("%d",&n);int x,y,z;
180     for(int i=1;i<n;i++){
181         scanf("%d%d%d",&x,&y,&z);
182         x++;y++;
183         init(x,y,z);init(y,x,z);
184     }tot=0;dfs1(1,1);dfs2(1,1);
185     build(1,1,n);
186     scanf("%d",&m);
187     for(int i=1;i<=m;i++){
188         scanf("%s%d%d",&ch,&x,&y);
189         if(ch[0]==N) mrev(x+1,y+1);
190         else if(ch[0]==C)cov(1,pos[crs[x]],pos[crs[x]],y);
191         else if(ch[1]==U)doit(x+1,y+1,0);
192         else if(ch[1]==A)doit(x+1,y+1,1);
193         else if(ch[1]==I)doit(x+1,y+1,2);
194     }
195     return 0;
196 }
View Code

 

以上是关于BZOJ2157: 旅游 树链剖分 线段树的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2157: 旅游树链剖分+线段树

BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)BZOJ计划

BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)BZOJ计划

BZOJ 2157 旅行(树链剖分码农题)

bzoj 1036 树链剖分+线段树 裸题

bzoj2243: [SDOI2011]染色--线段树+树链剖分