AC日记——[ZJOI2015]幻想乡战略游戏 洛谷 P3345
思路:
树剖暴力转移;
代码:
#include <bits/stdc++.h> using namespace std; #define maxn 100005 #define ll long long struct TreeNodeType { ll l,r,sum,mid; }; struct TreeNodeType tree[maxn<<2]; ll n,m,head[maxn],E[maxn<<1],V[maxn<<1],W[maxn<<1],cnt; ll id[maxn],sum[maxn],f[maxn],top[maxn],deep[maxn],size[maxn]; ll lar[maxn],dis[maxn],End[maxn],live,P=1,Sum; inline void in(ll &now) { ll if_z=1;now=0; char Cget=getchar(); while(Cget>'9'||Cget<'0') { if(Cget=='-') if_z=-1; Cget=getchar(); } while(Cget>='0'&&Cget<='9') { now=now*10+Cget-'0'; Cget=getchar(); } now*=if_z; } inline void edge_add(ll u,ll v,ll w) { E[++cnt]=head[u],V[cnt]=v,W[cnt]=w,head[u]=cnt; E[++cnt]=head[v],V[cnt]=u,W[cnt]=w,head[v]=cnt; } void dfs1(ll now,ll fa) { f[now]=fa,deep[now]=deep[fa]+1,size[now]=1; for(ll i=head[now];i;i=E[i]) { if(V[i]==f[now]) continue; dis[V[i]]=dis[now]+W[i],dfs1(V[i],now),size[now]+=size[V[i]]; if(size[lar[now]]<size[V[i]]) lar[now]=V[i]; } } void dfs2(ll now,ll chain) { top[now]=chain,id[now]=++cnt; if(lar[now]) dfs2(lar[now],chain); for(ll i=head[now];i;i=E[i]) { if(V[i]==lar[now]||V[i]==f[now]) continue; dfs2(V[i],V[i]); } End[now]=cnt; } ll find(ll x,ll y) { while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) y=f[top[y]]; else x=f[top[x]]; } return deep[x]<deep[y]?x:y; } void build(ll now,ll l,ll r) { tree[now].l=l,tree[now].r=r; if(l==r) return;tree[now].mid=l+r>>1; build(now<<1,l,tree[now].mid); build(now<<1|1,tree[now].mid+1,r); } void add(ll now,ll to,ll x) { if(tree[now].l==tree[now].r) { tree[now].sum+=x; return; } if(to<=tree[now].mid) add(now<<1,to,x); else add(now<<1|1,to,x); tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum; } ll query(ll now,ll to) { if(tree[now].l>=id[to]&&tree[now].r<=End[to]) return tree[now].sum; ll res=0;if(id[to]<=tree[now].mid) res+=query(now<<1,to); if(End[to]>tree[now].mid) res+=query(now<<1|1,to);return res; } ll Try(ll to) { ll pos=query(1,to),res=live; res-=pos*(dis[to]-dis[P]); res+=(Sum-pos)*(dis[to]-dis[P]); return res; } ll TryF() { ll pos=query(1,P),res=live; res-=(Sum-pos)*(dis[P]-dis[f[P]]); res+=pos*(dis[P]-dis[f[P]]); return res; } ll Search() { ll res=0,res_=live,pos; for(ll i=head[P];i;i=E[i]) { if(V[i]==f[P]) { pos=TryF(); if(pos<res_) res=V[i],res_=pos; } else { pos=Try(V[i]); if(pos<res_) res=V[i],res_=pos; } } if(res) P=res,live=res_; return res; } int main() { //freopen("data.txt","r",stdin); freopen("zjoi15_tree.in","r",stdin); freopen("zjoi15_tree.out","w",stdout); in(n),in(m);ll u,v,w,lca,tmp; for(ll i=1;i<n;i++) in(u),in(v),in(w),edge_add(u,v,w); cnt=0,dfs1(1,0),dfs2(1,1),build(1,1,n); while(m--) { in(u),in(w),add(1,id[u],w),lca=find(P,u),Sum+=w; live+=w*(dis[u]+dis[P]-dis[lca]*2); while(Search());printf("%lld\n",live); } return 0; }