Bzoj 1984: 月下“毛景树” 树链剖分
1984: 月下“毛景树”
Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1282 Solved: 410
[Submit][Status][Discuss]
Description
毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数: Change k w:将第k条树枝上毛毛果的个数改变为w个。 Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。 Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问: Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
Input
第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。
Output
对于毛毛虫的每个询问操作,输出一个答案。
Sample Input
4
1 2 8
1 3 7
3 4 9
Max 2 4
Cover 2 4 5
Add 1 4 10
Change 1 16
Max 2 4
Stop
1 2 8
1 3 7
3 4 9
Max 2 4
Cover 2 4 5
Add 1 4 10
Change 1 16
Max 2 4
Stop
Sample Output
9
16
【Data Range】
1<=N<=100,000,操作+询问数目不超过100,000。
保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。
16
【Data Range】
1<=N<=100,000,操作+询问数目不超过100,000。
保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。
HINT
Source
题解:
挺好的一道题。(处理边权的经典题)
其实就是把每条边上的权值放到这条边下方的点上即可。(这里Orz Popoqqq)
然后就是直接树链剖分即可。。。
但是一定要打标记。(两个标记:add和cover标记。)
而且,一定要先处理 覆盖标记 ,再处理 加数标记 。
因为询问时比如到了[l,r]区间,[l,r]区间原来的标记已经被下传过了。(就是如果原来有add标记,我现在要打个cover标记时,原来的add标记就要被清空。)所以询问时先覆盖,再加数。(加数一定是在覆盖后的数上加。)
然后用线段树维护一下即可。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 100010 4 #define INF 1e9 5 struct node 6 { 7 int begin,end,next; 8 }edge[MAXN*2]; 9 struct NODE 10 { 11 int left,right,a,c,mx; 12 }tree[MAXN*5]; 13 int cnt,Head[MAXN],pos[MAXN],size[MAXN],deep[MAXN],P[MAXN][17],chain[MAXN],belong[MAXN],id[MAXN],vv[MAXN],UU[MAXN],VV[MAXN],WW[MAXN],SIZE,n; 14 bool vis[MAXN]; 15 void addedge(int bb,int ee) 16 { 17 edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt; 18 } 19 void addedge1(int bb,int ee) 20 { 21 addedge(bb,ee);addedge(ee,bb); 22 } 23 int read() 24 { 25 int s=0,fh=1;char ch=getchar(); 26 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 27 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 28 return s*fh; 29 } 30 void dfs1(int u) 31 { 32 int i,v; 33 size[u]=1;vis[u]=true; 34 for(i=Head[u];i!=-1;i=edge[i].next) 35 { 36 v=edge[i].end; 37 if(vis[v]==false) 38 { 39 deep[v]=deep[u]+1; 40 P[v][0]=u; 41 dfs1(v); 42 size[u]+=size[v]; 43 } 44 } 45 } 46 void Ycl() 47 { 48 int i,j; 49 for(j=1;(1<<j)<=n;j++) 50 { 51 for(i=1;i<=n;i++) 52 { 53 if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1]; 54 } 55 } 56 } 57 void dfs2(int u,int chain) 58 { 59 int k=0,i,v; 60 pos[u]=++SIZE;belong[u]=chain; 61 for(i=Head[u];i!=-1;i=edge[i].next) 62 { 63 v=edge[i].end; 64 if(deep[v]>deep[u]&&size[v]>size[k])k=v; 65 } 66 if(k==0)return; 67 dfs2(k,chain); 68 for(i=Head[u];i!=-1;i=edge[i].next) 69 { 70 v=edge[i].end; 71 if(deep[v]>deep[u]&&v!=k)dfs2(v,v); 72 } 73 } 74 int LCA(int x,int y) 75 { 76 int i,j; 77 if(deep[x]<deep[y])swap(x,y); 78 for(i=0;(1<<i)<=deep[x];i++);i--; 79 for(j=i;j>=0;j--)if(deep[x]-(1<<j)>=deep[y])x=P[x][j]; 80 if(x==y)return x; 81 for(j=i;j>=0;j--) 82 { 83 if(P[x][j]!=-1&&P[x][j]!=P[y][j]) 84 { 85 x=P[x][j]; 86 y=P[y][j]; 87 } 88 } 89 return P[x][0]; 90 } 91 void Pushup(int k) 92 { 93 tree[k].mx=max(tree[k*2].mx,tree[k*2+1].mx); 94 } 95 void Update1(int k,int k1) 96 { 97 tree[k].mx=k1;tree[k].a=0;tree[k].c=k1; 98 } 99 void Update2(int k,int k1) 100 { 101 tree[k].a+=k1;tree[k].mx+=k1; 102 } 103 void Pushdown(int k) 104 { 105 int l=k*2,r=k*2+1; 106 if(tree[k].c!=-1) 107 { 108 Update1(l,tree[k].c);Update1(r,tree[k].c); 109 tree[k].c=-1; 110 } 111 if(tree[k].a!=0) 112 { 113 Update2(l,tree[k].a);Update2(r,tree[k].a); 114 tree[k].a=0; 115 } 116 } 117 void Build(int k,int l,int r) 118 { 119 tree[k].left=l;tree[k].right=r;tree[k].c=-1;tree[k].a=0; 120 if(l==r){tree[k].mx=vv[l];return;} 121 int mid=(l+r)/2; 122 Build(k*2,l,mid);Build(k*2+1,mid+1,r); 123 Pushup(k); 124 } 125 int Query_max(int k,int l,int r) 126 { 127 if(l<=tree[k].left&&tree[k].right<=r)return tree[k].mx; 128 Pushdown(k); 129 int mid=(tree[k].left+tree[k].right)/2; 130 if(r<=mid)return Query_max(k*2,l,r); 131 else if(l>mid)return Query_max(k*2+1,l,r); 132 else return max(Query_max(k*2,l,mid),Query_max(k*2+1,mid+1,r)); 133 } 134 void Add(int k,int l,int r,int A) 135 { 136 if(l<=tree[k].left&&tree[k].right<=r){tree[k].a+=A;tree[k].mx+=A;return;} 137 Pushdown(k); 138 int mid=(tree[k].left+tree[k].right)/2; 139 if(r<=mid)Add(k*2,l,r,A); 140 else if(l>mid)Add(k*2+1,l,r,A); 141 else {Add(k*2,l,mid,A);Add(k*2+1,mid+1,r,A);} 142 Pushup(k); 143 } 144 void Cover(int k,int l,int r,int C) 145 { 146 if(l<=tree[k].left&&tree[k].right<=r){tree[k].c=C;tree[k].a=0;tree[k].mx=C;return;} 147 Pushdown(k); 148 int mid=(tree[k].left+tree[k].right)/2; 149 if(r<=mid)Cover(k*2,l,r,C); 150 else if(l>mid)Cover(k*2+1,l,r,C); 151 else {Cover(k*2,l,mid,C);Cover(k*2+1,mid+1,r,C);} 152 Pushup(k); 153 } 154 int Solve_max(int x,int f) 155 { 156 int MAX=-INF; 157 while(belong[x]!=belong[f]) 158 { 159 MAX=max(MAX,Query_max(1,pos[belong[x]],pos[x])); 160 x=P[belong[x]][0]; 161 } 162 if(f!=x)MAX=max(MAX,Query_max(1,pos[f]+1,pos[x])); 163 return MAX; 164 } 165 void Solve_add(int x,int f,int add) 166 { 167 while(belong[x]!=belong[f]) 168 { 169 Add(1,pos[belong[x]],pos[x],add); 170 x=P[belong[x]][0]; 171 } 172 if(x!=f)Add(1,pos[f]+1,pos[x],add); 173 } 174 void Solve_cover(int x,int f,int cover) 175 { 176 while(belong[x]!=belong[f]) 177 { 178 Cover(1,pos[belong[x]],pos[x],cover); 179 x=P[belong[x]][0]; 180 } 181 if(x!=f)Cover(1,pos[f]+1,pos[x],cover); 182 } 183 int main() 184 { 185 int i,U,V,W,lca,k; 186 char zs[10]; 187 n=read(); 188 memset(Head,-1,sizeof(Head));cnt=1; 189 for(i=1;i<n;i++){UU[i]=read(),VV[i]=read(),WW[i]=read();addedge1(UU[i],VV[i]);} 190 memset(P,-1,sizeof(P));SIZE=0; 191 dfs1(1);Ycl(); 192 dfs2(1,1); 193 memset(id,0,sizeof(id)); 194 for(i=1;i<n;i++)//存储每条边下方的点. 195 { 196 if(deep[UU[i]]>deep[VV[i]])id[i]=UU[i]; 197 else id[i]=VV[i]; 198 } 199 for(i=1;i<n;i++)vv[pos[id[i]]]=WW[i]; 200 Build(1,1,n); 201 while(1) 202 { 203 scanf("\n%s",zs); 204 if(zs[0]=='S')break; 205 if(zs[0]=='M') 206 { 207 U=read();V=read(); 208 lca=LCA(U,V); 209 printf("%d\n",max(Solve_max(U,lca),Solve_max(V,lca))); 210 } 211 else if(zs[0]=='A') 212 { 213 U=read();V=read();W=read(); 214 lca=LCA(U,V); 215 Solve_add(U,lca,W);Solve_add(V,lca,W); 216 } 217 else 218 { 219 if(zs[1]=='o') 220 { 221 U=read();V=read();W=read(); 222 lca=LCA(U,V); 223 Solve_cover(U,lca,W);Solve_cover(V,lca,W); 224 } 225 else 226 { 227 k=read();W=read(); 228 vv[pos[id[k]]]=W; 229 Cover(1,pos[id[k]],pos[id[k]],W); 230 } 231 } 232 } 233 return 0; 234 }