ZJOI2015 幻想乡战略游戏
题目描述:
题解:
动态点分治。
记录点分树子树中到该点的所有价值。
为啥别人100行我150啊。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N = 100050; template<typename T> inline void read(T&x) { T f = 1,c = 0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} x = f*c; } int n,Q,hed[N],cnt; struct EG { int to,nxt; ll w; }e[N<<1]; void ae(int f,int t,ll w) { e[++cnt].to = t; e[cnt].nxt = hed[f]; e[cnt].w = w; hed[f] = cnt; } int dep[N],siz[N],fa[N],son[N],top[N]; ll dis[N]; void dfs0(int u,int f) { fa[u] = f,siz[u] = 1,dep[u] = dep[f]+1; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(to==f)continue; dis[to] = dis[u]+e[j].w; dfs0(to,u); siz[u]+=siz[to]; if(siz[to]>siz[son[u]])son[u]=to; } } void dfs1(int u,int Top) { top[u] = Top; if(son[u])dfs1(son[u],Top); for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(to!=fa[u]&&to!=son[u]) dfs1(to,to); } } int get_lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); x = fa[top[x]]; } return dep[x]<dep[y]?x:y; } ll get_dis(int x,int y){return dis[x]+dis[y]-2ll*dis[get_lca(x,y)];} ll get_dis(int x,int y,int l){return dis[x]+dis[y]-2ll*dis[l];} int sum,rt,sz[N],mx[N],ff[N]; ll k1[N],k2[N],k3[N]; bool mrk[N]; void get_rt(int u,int f) { mx[u] = 0,sz[u] = 1; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(to==f||mrk[to])continue; get_rt(to,u); sz[u]+=sz[to]; mx[u] = max(mx[u],sz[to]); } mx[u] = max(mx[u],sum-sz[u]); if(mx[u]<mx[rt])rt=u; } void work(int u) { mrk[u] = 1;int tmp = sum; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(mrk[to])continue; rt=0,sum=(sz[to]>sz[u])?tmp-sz[u]:sz[to]; get_rt(to,0);ff[rt]=u;work(rt); } } int Rt=1; ll ans,ds[N][22]; void up(int x,ll y) { for(int i=x,j=0,k=0;i;j=i,i=ff[i],k++) { ll now = y*ds[x][k]; k1[i]+=now;k3[i]+=y; if(j)k2[j]+=now; } } ll query(int x) { ll ret = 0; for(int i=x,j=0,k=0;i;j=i,i=ff[i],k++) ret+=k1[i]-k2[i]+(k3[i]-k3[j])*ds[x][k]; return ret; } int turn() { int son = 0;ll bas = query(Rt); for(int j=hed[Rt];j;j=e[j].nxt) { int to = e[j].to;ll tmp = query(to); if(tmp<bas)son=to,bas=tmp; } if(!son)return 0; Rt = son;return 1; } int main() { // freopen("1.in","r",stdin); read(n),read(Q); for(int u,v,w,i=1;i<n;i++) { read(u),read(v),read(w); ae(u,v,w),ae(v,u,w); } dfs0(1,0),dfs1(1,1); mx[rt=0]=0x3f3f3f3f,sum=n; get_rt(1,0);work(rt); for(int i=1;i<=n;i++) for(int j=1,k=ff[i];k;j++,k=ff[k]) ds[i][j]=get_dis(i,k); int x,y; read(x),read(y); Rt = x,ans = 0;up(x,y); puts("0"); for(int i=2;i<=Q;i++) { read(x),read(y); up(x,y); while(turn()); printf("%lld\n",query(Rt)); } return 0; }