BZOJ P2157 旅游
题目大意:
维护一棵树,每条边有边权,支持下列操作:
1.修改某条边的边权
2.将某条路经上的边权取反
3.询问某条路经上的和
4.询问某条路经上的最大值
5.询问某条路经上的最小值
--by BZOJ;
http://www.lydsy.com/JudgeOnline/problem.php?id=2157
有关树链剖分的详解,见:树链剖分
链剖模板,代码长了点,主要是线段树部分操作太多,注意可以把边权搞到点上;
代码如下:
1 #include<cstdio> 2 #define INF 0x3fffffff 3 using namespace std; 4 struct ss{ 5 int to,next,dis; 6 }x[40001]; 7 int first[20001],num; 8 int size[20001];//子树和// 9 int hway[20001];//重边// 10 int rank[20001];//点在line_tree中的位置// 11 int rankl[20001];//边所对点在line_tree中的位置// 12 int dis[20001];//点权 // 13 int top[20001];//重链顶 // 14 int dep[20001];//深度 // 15 int fa[20001];//父亲// 16 int a[20001];//line_tree的原line序列// 17 int ltre[100005]; 18 int max[100005]; 19 int min[100005]; 20 int lz[100005]; 21 int n,m,L,R,X,W; 22 void swap(int&,int&); 23 void build(int ,int ,int ); 24 void dfs_1(int ); 25 void dfs_2(int ,int ); 26 void up(int ); 27 void down(int ,int ,int ); 28 void builtre(int ,int ,int ); 29 void work(int ); 30 int wor_(int ,int ); 31 void chan1(int ,int ,int ); 32 void chan2(int ,int ,int ); 33 int sum(int ,int ,int ); 34 int Max(int ,int ,int ); 35 int Min(int ,int ,int ); 36 int main() 37 { 38 int i,j,k,l; 39 char s[50]; 40 scanf("%d",&n); 41 for(i=0;i<=n-1;i++) 42 hway[i]=i; 43 for(i=1;i<=n-1;i++){ 44 scanf("%d%d%d",&j,&k,&l); 45 build(j,k,l); 46 build(k,j,l); 47 } 48 dep[0]=1; 49 dfs_1(0); 50 num=0; 51 dfs_2(0,0); 52 num=0; 53 builtre(1,n,1); 54 scanf("%d",&m); 55 for(i=1;i<=m;i++){ 56 scanf("%s",s); 57 scanf("%d%d",&L,&R); 58 if(s[1]!='\0')s[0]=s[1]; 59 if(s[0]=='C')X=rankl[L],W=R; 60 switch (s[0]){ 61 case 'C': chan1(1,n,1);break;//C 62 case 'N': work(2);break;//N 63 case 'U': work(3);break;//NUM 64 case 'A': work(4);break;//MAX 65 case 'I': work(5);break;//MIN 66 } 67 } 68 } 69 void swap(int &a,int &b){ 70 int i; 71 i=a;a=b;b=i; 72 } 73 void build(int f,int t,int l){ 74 x[++num].next=first[f]; 75 x[num].dis=l; 76 x[num].to=t; 77 first[f]=num; 78 } 79 void dfs_1(int now){ 80 int j=first[now]; 81 while(j){ 82 if(!dep[x[j].to]){ 83 dis[x[j].to]=x[j].dis; 84 dep[x[j].to]=dep[now]+1; 85 fa[x[j].to]=now; 86 dfs_1(x[j].to); 87 size[now]+=size[x[j].to]; 88 if(hway[now]==now||size[x[j].to]>size[hway[now]]) 89 hway[now]=x[j].to; 90 } 91 j=x[j].next; 92 } 93 size[now]++; 94 } 95 void dfs_2(int now,int to_nu){ 96 int j=first[now]; 97 top[now]=to_nu; 98 rank[now]=++num; 99 a[num]=now; 100 if(hway[now]!=now) 101 dfs_2(hway[now],to_nu); 102 while(j){ 103 if(dep[x[j].to]>dep[now]&&x[j].to!=hway[now]) 104 rankl[(j+1)>>1]=num+1,dfs_2(x[j].to,x[j].to); 105 if(x[j].to==hway[now]) 106 rankl[(j+1)>>1]=rank[hway[now]]; 107 j=x[j].next; 108 } 109 } 110 void up(int nu){ 111 ltre[nu]=ltre[nu<<1]+ltre[nu<<1|1]; 112 max[nu]=max[nu<<1]>max[nu<<1|1]?max[nu<<1]:max[nu<<1|1]; 113 min[nu]=min[nu<<1]<min[nu<<1|1]?min[nu<<1]:min[nu<<1|1]; 114 } 115 void down(int l,int r,int nu){ 116 if(!lz[nu]) return; 117 lz[nu<<1]^=1;lz[nu<<1|1]^=1; 118 swap(max[nu<<1],min[nu<<1]); 119 max[nu<<1]=-max[nu<<1]; min[nu<<1]=-min[nu<<1]; 120 ltre[nu<<1]=-ltre[nu<<1]; 121 swap(max[nu<<1|1],min[nu<<1|1]); 122 max[nu<<1|1]=-max[nu<<1|1]; min[nu<<1|1]=-min[nu<<1|1]; 123 ltre[nu<<1|1]=-ltre[nu<<1|1]; 124 lz[nu]=0; 125 } 126 void builtre(int l,int r,int nu){ 127 if(l==r){ 128 max[nu]=min[nu]=ltre[nu]=dis[a[++num]]; 129 if(a[num]==0){ 130 max[nu]=-INF; 131 min[nu]=INF; 132 } 133 return; 134 } 135 int mid=(l+r)>>1; 136 builtre(l,mid,nu<<1); 137 builtre(mid+1,r,nu<<1|1); 138 up(nu); 139 } 140 void work(int x){ 141 int ans=0; 142 if(x==4)ans=-INF; 143 if(x==5)ans=INF; 144 int u=L,v=R; 145 while(top[u]!=top[v]){ 146 if(dep[top[u]]<dep[top[v]]) 147 L=rank[top[v]],R=rank[v],v=fa[top[v]]; 148 else 149 L=rank[top[u]],R=rank[u],u=fa[top[u]]; 150 ans=wor_(ans,x); 151 } 152 if(u!=v){ 153 if(dep[u]>dep[v]) 154 swap(u,v); 155 u=hway[u]; 156 L=rank[u];R=rank[v]; 157 ans=wor_(ans,x); 158 } 159 if(x>=3) 160 printf("%d\n",ans); 161 } 162 int wor_(int ans,int x){ 163 int i; 164 if(x==2) 165 chan2(1,n,1); 166 if(x==3) 167 ans+=sum(1,n,1); 168 if(x==4){ 169 i=Max(1,n,1);ans=ans>i?ans:i;} 170 if(x==5){ 171 i=Min(1,n,1);ans=ans<i?ans:i;} 172 return ans; 173 } 174 void chan1(int l,int r,int nu){ 175 if(l==r){ 176 max[nu]=min[nu]=ltre[nu]=W ; 177 return; 178 } 179 int mid=(l+r)>>1; 180 down(l,r,nu); 181 if(X<=mid) 182 chan1(l,mid,nu<<1); 183 if(X>mid) 184 chan1(mid+1,r,nu<<1|1); 185 up(nu); 186 } 187 void chan2(int l,int r,int nu){ 188 if(L<=l&&r<=R){ 189 swap(max[nu],min[nu]); 190 max[nu]=-max[nu]; 191 min[nu]=-min[nu]; 192 ltre[nu]=-ltre[nu]; 193 lz[nu]^=1; 194 return ; 195 } 196 down(l,r,nu); 197 int mid=(l+r)>>1; 198 if(L<=mid) 199 chan2(l,mid,nu<<1); 200 if(R>mid) 201 chan2(mid+1,r,nu<<1|1); 202 up(nu); 203 } 204 int sum(int l,int r,int nu){ 205 if(L<=l&&r<=R) 206 return ltre[nu]; 207 down(l,r,nu); 208 int mid=(l+r)>>1,re=0; 209 if(L<=mid) 210 re+=sum(l,mid,nu<<1); 211 if(R>mid) 212 re+=sum(mid+1,r,nu<<1|1); 213 return re; 214 } 215 int Max(int l,int r,int nu){ 216 if(L<=l&&r<=R) 217 return max[nu]; 218 down(l,r,nu); 219 int mid=(l+r)>>1,lm=-INF,rm=-INF; 220 if(L<=mid) 221 lm=Max(l,mid,nu<<1); 222 if(R>mid) 223 rm=Max(mid+1,r,nu<<1|1); 224 if(lm>=rm) 225 return lm; 226 return rm; 227 } 228 int Min(int l,int r,int nu){ 229 if(L<=l&&r<=R) 230 return min[nu]; 231 down(l,r,nu); 232 int mid=(l+r)>>1,lm=INF,rm=INF; 233 if(L<=mid) 234 lm=Min(l,mid,nu<<1); 235 if(R>mid) 236 rm=Min(mid+1,r,nu<<1|1); 237 if(lm<=rm) 238 return lm; 239 return rm; 240 }
祝AC哟;
Just close your eyes, you`ll be alright, no one can hurt you after you die.