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 }
以上是关于BZOJ2157: 旅游 树链剖分 线段树的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)BZOJ计划