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 Sample Output 9 16 【Data Range】 1<=N<=100,000,操作+询问数目不超过100,000。 保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。
解题思路:边权化点权,将边权放到深度较深的点上面
对于操作:
Change k w:将第k条树枝上毛毛果的个数改变为w个。
=>直接找对应的点,线段树上单点修改
Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。
=>注意:u和v的lca是不应该被修改的
为了方便,我们可以先修改,再把lca改回去
Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。
=>注意:u和v的lca是不应该被加的
为了方便,我们可以先修改,再把lca减回去
Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
=>注意:u和v的lca是不应该被算进去的
我们可以先将lca赋成极小值
得到答案后在将原值赋回去
值得注意的地方是线段树的标记下放:
先修改操作,后加操作,保证正确性
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const ll N=1e5+10; 5 struct node{ 6 ll u,v,c,ne; 7 }e[N*2]; 8 ll h[N],tot,n; 9 void add(ll u,ll v,ll c) 10 { 11 tot++;e[tot]=(node){u,v,c,h[u]};h[u]=tot; 12 e[tot+n-1]=(node){v,u,c,h[v]};h[v]=tot+n-1; 13 } 14 ll dep[N],size[N],son[N],f[N]; 15 ll val[N],w[N],id[N],top[N]; 16 ll Max[N*6],ad[N*6],fg[N*6]; 17 void build(ll o,ll l,ll r) 18 { 19 fg[o]=-1;ad[o]=0; 20 if(l==r){ 21 Max[o]=w[l]; 22 return; 23 } 24 ll mid=(l+r)>>1; 25 build(o<<1,l,mid);build(o<<1|1,mid+1,r); 26 Max[o]=max(Max[o<<1],Max[o<<1|1]); 27 } 28 void down(ll o) 29 { 30 if(fg[o]!=-1) 31 { 32 fg[o<<1]=Max[o<<1]=fg[o]; 33 fg[o<<1|1]=Max[o<<1|1]=fg[o]; 34 ad[o<<1]=ad[o<<1|1]=0; 35 fg[o]=-1; 36 } 37 if(ad[o]) 38 { 39 Max[o<<1]+=ad[o];Max[o<<1|1]+=ad[o]; 40 if(fg[o<<1]!=-1) fg[o<<1]+=ad[o]; 41 else ad[o<<1]+=ad[o]; 42 if(fg[o<<1|1]!=-1) fg[o<<1|1]+=ad[o]; 43 else ad[o<<1|1]+=ad[o]; 44 ad[o]=0; 45 } 46 } 47 void tchange(ll o,ll l,ll r,ll x,ll y,ll k) 48 { 49 if(x<=l && y>=r) 50 { 51 Max[o]=k;fg[o]=k;ad[o]=0; 52 return; 53 } 54 down(o); 55 ll mid=(l+r)>>1; 56 if(x<=mid) tchange(o<<1,l,mid,x,y,k); 57 if(y>=mid+1) tchange(o<<1|1,mid+1,r,x,y,k); 58 Max[o]=max(Max[o<<1],Max[o<<1|1]); 59 } 60 void tadd(ll o,ll l,ll r,ll x,ll y,ll k) 61 { 62 if(x<=l && y>=r) 63 { 64 ad[o]+=k;Max[o]+=k; 65 return; 66 } 67 down(o); 68 ll mid=(l+r)>>1; 69 if(x<=mid) tadd(o<<1,l,mid,x,y,k); 70 if(y>=mid+1) tadd(o<<1|1,mid+1,r,x,y,k); 71 Max[o]=max(Max[o<<1],Max[o<<1|1]); 72 } 73 ll tquery(ll o,ll l,ll r,ll x,ll y) 74 { 75 if(x<=l && y>=r) return Max[o]; 76 down(o); 77 ll mid=(l+r)>>1,tmp=-1e9; 78 if(x<=mid) tmp=max(tmp,tquery(o<<1,l,mid,x,y)); 79 if(y>=mid+1) tmp=max(tmp,tquery(o<<1|1,mid+1,r,x,y)); 80 return tmp; 81 } 82 void dfs1(ll u) 83 { 84 size[u]=1;ll p=-1; 85 for(ll i=h[u],rr;i;i=e[i].ne) 86 { 87 rr=e[i].v; 88 if(!dep[rr]) 89 { 90 dep[rr]=dep[u]+1;f[rr]=u;val[rr]=e[i].c; 91 dfs1(rr);size[u]+=size[rr]; 92 if(size[rr]>p) 93 p=size[rr],son[u]=rr; 94 } 95 } 96 } 97 void dfs2(ll u,ll up) 98 { 99 if(u==0) return; 100 id[u]=++tot;w[tot]=val[u]; 101 top[u]=up; 102 dfs2(son[u],up); 103 for(ll i=h[u],rr;i;i=e[i].ne) 104 { 105 rr=e[i].v; 106 if(rr!=f[u] && rr!=son[u]) dfs2(rr,rr); 107 } 108 } 109 void Qchange(ll x,ll y,ll k) 110 { 111 while(top[x]!=top[y]) 112 { 113 if(dep[top[x]]<dep[top[y]]) swap(x,y); 114 tchange(1,1,n,id[top[x]],id[x],k); 115 x=f[top[x]]; 116 } 117 if(dep[x]>dep[y]) swap(x,y); 118 tchange(1,1,n,id[x],id[y],k); 119 } 120 void Qadd(ll x,ll y,ll k) 121 { 122 while(top[x]!=top[y]) 123 { 124 if(dep[top[x]]<dep[top[y]]) swap(x,y); 125 tadd(1,1,n,id[top[x]],id[x],k); 126 x=f[top[x]]; 127 } 128 if(dep[x]>dep[y]) swap(x,y); 129 tadd(1,1,n,id[x],id[y],k); 130 } 131 ll Qmax(ll x,ll y) 132 { 133 ll ans=-1; 134 while(top[x]!=top[y]) 135 { 136 if(dep[top[x]]<dep[top[y]]) swap(x,y); 137 ans=max(ans,tquery(1,1,n,id[top[x]],id[x])); 138 x=f[top[x]]; 139 } 140 if(dep[x]>dep[y]) swap(x,y); 141 ans=max(ans,tquery(1,1,n,id[x],id[y])); 142 return ans; 143 } 144 ll lca(ll x,ll y) 145 { 146 while(top[x]!=top[y]) 147 { 148 if(dep[top[x]]<dep[top[y]]) swap(x,y); 149 x=f[top[x]]; 150 } 151 if(dep[x]>dep[y]) swap(x,y); 152 return x; 153 } 154 char op[10]; 155 ll x,y,z,fa,tmp; 156 int main() 157 { 158 scanf("%lld",&n); 159 for(ll i=1;i<=n-1;++i) 160 { 161 scanf("%lld%lld%lld",&x,&y,&z); 162 add(x,y,z); 163 } 164 dep[1]=1;dfs1(1); 165 val[1]=-1e9;tot=0;dfs2(1,1); 166 build(1,1,n); 167 while(scanf("%s",op)!=EOF) 168 { 169 if(op[1]=='t') break; 170 if(op[1]=='h')//将第x条树枝上毛毛果的个数改变为y个 171 { 172 scanf("%lld%lld",&x,&y); 173 x=(dep[e[x].u]>dep[e[x].v] ? e[x].u:e[x].v); 174 tchange(1,1,n,id[x],id[x],y); 175 } 176 if(op[1]=='o')//将节点x与节点y之间的都改变为z个 177 { 178 scanf("%lld%lld%lld",&x,&y,&z); 179 fa=lca(x,y);tmp=tquery(1,1,n,id[fa],id[fa]); 180 Qchange(x,y,z);tchange(1,1,n,id[fa],id[fa],tmp); 181 } 182 if(op[1]=='d')//将节点x与节点y之间的都增加z个 183 { 184 scanf("%lld%lld%lld",&x,&y,&z); 185 fa=lca(x,y); 186 Qadd(x,y,z);tadd(1,1,n,id[fa],id[fa],-z); 187 } 188 if(op[1]=='a')//询问节点x与节点y之间最多有多少个 189 { 190 scanf("%lld%lld",&x,&y); 191 fa=lca(x,y);tmp=tquery(1,1,n,id[fa],id[fa]); 192 tchange(1,1,n,id[fa],id[fa],-1e9); 193 printf("%lld ",Qmax(x,y)); 194 tchange(1,1,n,id[fa],id[fa],tmp); 195 } 196 } 197 return 0; 198 }