【BZOJ 3924】[Zjoi2015]幻想乡战略游戏
2017-12-08 19:10
411 查看
题目:
题解:
对点分树理解加深了233,膜拜zzh干翻紫荆花。感谢zzh的讲解。
首先优化基于传统DP,假设树不发生变化,我们就可以利用DP求出带权重心。
考虑修改,我们思路不变,还是从root开始找,但发现这样会被卡成$n^2$,原因是每次经过点太多,为了优化,考虑点分树,由于点分树的性质使得假设我们可以在点分树上找到最优解,那么每次最多经过$log$个节点,可以保证时间复杂度。
然后考虑在点分树转移,假设当前节点为x,我们枚举其在原树中的边,假设当前枚举边的另一端为y,那么由DP可以得出如果以当前边分为两半,若y的一半点权和大于所有点权的一半,那么最优解一定在y那边存在,然后我们由点分树直接跳跃到y对应的块中。若不存在这样的y,则x一定为最优解。
这样的话我们的目的就是求x点对应的答案以及y一边对应的点权和,我们用三个数组来记录当前x的点分子树的点权和,点分子树到达x的$d*dis$和,以及到达其父亲的$d*dis$和,这样统计x的答案就可以在$log$的时间内完成。
对于y我们可以开一个$log$大小的数组来记录在点分数上走过的点,并按照原树dfs排序,每次到达一个新的x用$log$更新,并在此序列上维护一个$sum$表示经过路径上x与其儿子s点权和之差,那么考虑若枚举的y是x在原树的儿子或父亲时的情况,分类讨论,利用$sum$快速求出y一边的点权和。
综上所述,时间复杂度为$O(20nlog_2^nlog_2^{log_2^n})$
代码:
#define Troy #define inf 0x7fffffff #include "bits/stdc++.h" using namespace std; inline int read(){ int s=0,k=1;char ch=getchar(); while (ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar(); while (ch>47&ch<='9') s=s*10+(ch^48),ch=getchar(); return s*k; } const int N=1e5+5; typedef long long ll; struct edges { int v,nv,w;edges *last; }edge[N<<1],*head ;int cnt; inline void push(int u,int v,int w){ edge[++cnt]=(edges){v,0,w,head[u]};head[u]=edge+cnt; } int bit[30]; class ST{ public: inline void build(int *a,int n){ lgs[0]=-1; register int i,j; for (i=1;i<=n;++i) lgs[i]=lgs[i>>1]+1,f[i][0]=a[i]; for (i=1;bit[i]<=n;++i) for (j=1;j+bit[i]<=n+1;++j) f[j][i]=min(f[j][i-1],f[j+bit[i-1]][i-1]); } inline int query(int l,int r){ if(r<l) swap(l,r);int t=lgs[r-l+1]; return min(f[l][t],f[r-bit[t]+1][t]); } private: int f[N<<1][20],lgs[N<<1]; }RMQ; int dis ,eular[N<<1],num,beg ,End ,n,m; inline void DFS(int x,int fa){ eular[beg[x]=++num]=dis[x]; for(edges *i=head[x];i;i=i->last) if(i->v^fa){ dis[i->v]=dis[x]+i->w; DFS(i->v,x); eular[++num]=dis[x]; }End[x]=num; } inline ll get_dis(int x,int y){ return dis[x]+dis[y]-(RMQ.query(beg[x],beg[y])<<1); } class Point_Divide_Tree{ public: int root,tot,fat ,size ,heavy ,dsum ; bool vis ; ll dissum ,fdissum ; inline void dfs(int x,int fa){ size[x]=1,heavy[x]=0; for(edges *i=head[x];i;i=i->last) if(i->v!=fa&&!vis[i->v]){ dfs(i->v,x),size[x]+=size[i->v]; heavy[x]=max(heavy[x],size[i->v]); }heavy[x]=max(heavy[x],tot-size[x]); if(heavy[root]>heavy[x]) root=x; } inline void build(int x,int fa){ root=0,dfs(x,0); vis[x=root]=true,fat[x]=fa,dfs(x,x); for (edges *i=head[x];i;i=i->last) if(!vis[i->v]){ tot=size[i->v]; build(i->v,x),i->nv=root; }root=x; } inline void insert(int x,int y,int val){ tot+=val; while(x){ dsum[x]+=val; dissum[x]+=get_dis(x,y)*val; if(fat[x]) fdissum[x]+=get_dis(fat[x],y)*val; x=fat[x]; } } ll ans,sum[30]; int pos[30],leth; inline int calc(int fa,int x,int real){ int ret=dsum[real]; if(dis[x]<dis[fa]){ int l=lower_bound(pos+1,pos+leth+1,beg[fa])-pos, r=upper_bound(pos+1,pos+leth+1,End[fa])-pos-1; ret+=sum[leth]-sum[r]+sum[l-1]; }else{ int l=lower_bound(pos+1,pos+leth+1,beg[x])-pos, r=upper_bound(pos+1,pos+leth+1,End[x])-pos-1; ret+=sum[r]-sum[l-1]; } return ret; } inline ll calc(int x){ ll ret=dissum[x]; int p=x; while(fat[x]){ ret+=(dsum[fat[x]]-dsum[x])*get_dis(fat[x],p)+dissum[fat[x]]-fdissum[x]; x=fat[x]; }return ret; } inline void update(int x,int y){ ll now=dsum[x]-dsum[y]; for(int i=leth+1;i;--i){ sum[i]=sum[i-1]+now; if(i==1||pos[i-1]<=beg[x]){ pos[i]=beg[x]; break; }else pos[i]=pos[i-1]; }++leth; } inline void query(int x){ for(edges *i=head[x];i;i=i->last) if(i->nv){ if(calc(x,i->v,i->nv)*2>=tot){ update(x,i->nv); ans=calc(i->nv); query(i->nv); break; } } } inline void query(){ leth=0; ans=dissum[root]; query(root); printf("%lld\n",ans); } }tree; int main(){ register int i,j; for (i=0;i<=20;++i) bit[i]=1<<i; n=read(),m=read(); for (i=1;i^n;++i){ int a=read(),b=read(),c=read(); push(a,b,c),push(b,a,c); } DFS(1,1),RMQ.build(eular,num); tree.tot=n,tree.heavy[0]=inf; tree.build(1,0),tree.tot=0; while(m--){ i=read(),j=read(); tree.insert(i,i,j); tree.query(); } }
相关文章推荐
- bzoj 3924: [Zjoi2015]幻想乡战略游戏
- bzoj3924 [Zjoi2015]幻想乡战略游戏(动态点分治)
- 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治
- [ZJOI2015][bzoj3924] 幻想乡战略游戏 [动态点分治]
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)
- bzoj 3924: [Zjoi2015]幻想乡战略游戏 动态树分治
- [BZOJ3924][ZJOI2015]幻想乡战略游戏(动态点分治)
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏
- BZOJ 3924 Zjoi2015 幻想乡战略游戏 动态树分治
- [BZOJ]3924 [ZJOI2015] 幻想乡战略游戏 树链剖分
- 【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治
- [点分树] BZOJ 3924 [Zjoi2015]幻想乡战略游戏
- bzoj 3924: [Zjoi2015]幻想乡战略游戏
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏 动态树分治
- bzoj3924 [Zjoi2015]幻想乡战略游戏
- 【BZOJ3924】【Zjoi2015】幻想乡战略游戏(树链剖分+点分治)
- 【BZOJ 3924】【ZJOI 2015】幻想乡战略游戏
- [BZOJ3924][ZJOI2015]幻想乡战略游戏-动态树分治
- BZOJ3924 : [Zjoi2015]幻想乡战略游戏