1. 程式人生 > >BZOJ2157: 旅遊 樹鏈剖分 線段樹

BZOJ2157: 旅遊 樹鏈剖分 線段樹

const ostream one size con head log alt 一行

http://www.lydsy.com/JudgeOnline/problem.php?id=2157 在對樹中數據進行改動的時候需要很多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: 旅遊 樹鏈剖分 線段樹