BZOJ3924: [Zjoi2015]幻想鄉戰略遊戲
阿新 • • 發佈:2018-12-23
math != i+1 bzoj3924 class val log 有一個 har
BZOJ3924: [Zjoi2015]幻想鄉戰略遊戲
https://lydsy.com/JudgeOnline/problem.php?id=3924
分析:
- 首先有一個很棒的思路,就是在點分樹上跳重心,每次向答案最小的子分治中心移動。
- 這個是對的,因為樹上帶權重心往旁邊的點走答案一定更差。
- 只需要每次能夠\(O(logn)?\)查詢即可,維護點分樹上子樹\(dist\times d?\)的和。
- 時間復雜度\(O(nlogn^2度數)\)
代碼:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; typedef long long ll; #define N 100050 #define db(x) cerr<<#x<<" = "<<x<<endl int head[N],to[N<<1],nxt[N<<1],cnt,n,m,val[N<<1]; int siz[N],fk[N],tot,root,dep[N],fa[N][20],used[N]; int sz[N],f[N<<1]; ll dis[N][20],sum[N],sum2[N]; inline void add(int u,int v,int w=0) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w; } char buf[100000],*p1,*p2; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() { int x=0,f=1; char s=nc(); while(s<'0') {if(s=='-') f=-1;s=nc();} while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc(); return x*f; } void gr(int x,int y) { int i; siz[x]=1; fk[x]=0; for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) { gr(to[i],x); siz[x]+=siz[to[i]]; fk[x]=max(fk[x],siz[to[i]]); } fk[x]=max(fk[x],tot-siz[x]); if(fk[x]<fk[root]) root=x; } void gd(int x,int y,int rt,int d) { fa[x][++dep[x]]=rt; dis[x][dep[x]]=d; int i; for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) { gd(to[i],x,rt,d+val[i]); } } void solve(int x) { used[x]=1; int i,all=tot; gd(x,0,x,0); for(i=head[x];i;i=nxt[i]) if(!used[to[i]]) { tot=siz[to[i]]; if(tot>siz[x]) tot=all-siz[x]; root=0; gr(to[i],x); f[i]=root; solve(root); } } void upd(int x,int v) { int i; for(i=dep[x];i;i--) { sum[fa[x][i]]+=dis[x][i]*v; sum2[fa[x][i]]+=dis[x][i-1]*v; sz[fa[x][i]]+=v; } } ll calc(int x) { int i; ll re=0; for(i=dep[x];i;i--) { re+=sum[fa[x][i]]-sum2[fa[x][i+1]]+(sz[fa[x][i]]-sz[fa[x][i+1]])*dis[x][i]; } return re; } int rt; ll query() { int x=rt,i; ll nowans=calc(x); while(1) { ll mn=1ll<<60; int p=0; for(i=head[x];i;i=nxt[i]) if(f[i]) { ll tmp=calc(to[i]); if(tmp<mn) mn=tmp,p=f[i]; } if(mn<nowans) x=p,nowans=calc(x); else return nowans; } } int main() { n=rd(),m=rd(); int i,x,y,z; for(i=1;i<n;i++) { x=rd(),y=rd(),z=rd(); add(x,y,z); add(y,x,z); } fk[0]=1<<30; tot=n; gr(1,0); rt=root; solve(root); while(m--) { x=rd(),y=rd(); upd(x,y); printf("%lld\n",query()); } } /* 10 5 1 2 1 2 3 1 2 4 1 1 5 1 2 6 1 2 7 1 5 8 1 7 9 1 1 10 1 3 1 2 1 8 1 3 1 4 1 */
BZOJ3924: [Zjoi2015]幻想鄉戰略遊戲