[ZJOI2015]幻想乡战略游戏
Description
傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打仗了。 在打仗之前,幽香现在面临一个非常基本的管理问题需要解决。 整个地图是一个树结构,一共有n块空地,这些空地被n-1条带权边连接起来,使得每两个点之间有一条唯一的路径将它们连接起来。在游戏中,幽香可能在空地上增加或者减少一些军队。同时,幽香可以在一个空地上放置一个补给站。 如果补给站在点u上,并且空地v上有dv个单位的军队,那么幽香每天就要花费dv×dist(u,v)的金钱来补给这些军队。由于幽香需要补给所有的军队,因此幽香总共就要花费为Sigma(Dv*dist(u,v),其中1<=V<=N)的代价。其中dist(u,v)表示u个v在树上的距离(唯一路径的权和)。 因为游戏的规定,幽香只能选择一个空地作为补给站。在游戏的过程中,幽香可能会在某些空地上制造一些军队,也可能会减少某些空地上的军队,进行了这样的操作以后,出于经济上的考虑,幽香往往可以移动他的补给站从而省一些钱。但是由于这个游戏的地图是在太大了,幽香无法轻易的进行最优的安排,你能帮帮她吗? 你可以假定一开始所有空地上都没有军队。
Input
第一行两个数n和Q分别表示树的点数和幽香操作的个数,其中点从1到n标号。
接下来n-1行,每行三个正整数a,b,c,表示a和b之间有一条边权为c的边。
接下来Q行,每行两个数u,e,表示幽香在点u上放了e单位个军队
(如果e<0,就相当于是幽香在u上减少了|e|单位个军队,说白了就是du←du+e)。
数据保证任何时刻每个点上的军队数量都是非负的。
1<=c<=1000, 0<=|e|<=1000, n<=10^5, Q<=10^5
对于所有数据,这个树上所有点的度数都不超过20
N,Q>=1
Output
对于幽香的每个操作,输出操作完成以后,每天的最小花费,也即如果幽香选择最优的补给点进行补给时的花费。
Sample Input
10 5
1 2 1
2 3 1
2 4 1
1 5 1
2 61
2 7 1
5 8 1
7 91
1 10 1
3 1
2 1
8 1
3 1
4 1
1 2 1
2 3 1
2 4 1
1 5 1
2 61
2 7 1
5 8 1
7 91
1 10 1
3 1
2 1
8 1
3 1
4 1
Sample Output
0
1
4
5
6
1
4
5
6
先假设1为补给站
那么相邻节点x满足军队数s[x]>=w-s[x]
那么把补给站移到x显然更好,因为减少的比增加的人多
也就是说,在满足2*s[x]>=w的情况下,尽量往下走
也就是找到满足条件dfs序编号最大的
ans(x)=∑d[i]dist(i,x)=∑d[i](dep[i]+dep[x]-2*dep[lca])
=∑d[i]dep[i]+∑d[i]dep[x]-2*∑d[i]dep[lca]
前两个不用管,最后一个可以这样:
给u加e的军队,那么就给1~u都加上e,查询时查询1~x的路径和
这样就等于答案加上了e*dep[lca]
用树链剖分+线段树维护区间和,最大值和延迟标记
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long lol; 8 struct Node 9 { 10 int next,to; 11 lol dis; 12 }edge[200001]; 13 int num,head[100001],size[100001],fa[100001],son[100001]; 14 int top[100001],dfn[100001],id[100001],cnt,n,Q; 15 lol lazy[400001],c[400001],mx[400001],s[400001],dep[100001]; 16 void add(int u,int v,lol w) 17 { 18 num++; 19 edge[num].next=head[u]; 20 head[u]=num; 21 edge[num].to=v; 22 edge[num].dis=w; 23 } 24 void dfs1(int x,int pa) 25 {int i; 26 size[x]=1; 27 for (i=head[x];i;i=edge[i].next) 28 { 29 int v=edge[i].to; 30 if (v!=pa) 31 { 32 fa[v]=x; 33 dep[v]=dep[x]+edge[i].dis; 34 dfs1(v,x); 35 size[x]+=size[v]; 36 if (size[v]>size[son[x]]) son[x]=v; 37 } 38 } 39 } 40 void dfs2(int x,int pa,int tp) 41 {int i; 42 top[x]=tp; 43 dfn[x]=++cnt;id[cnt]=x; 44 if (son[x]) dfs2(son[x],x,tp); 45 for (i=head[x];i;i=edge[i].next) 46 { 47 int v=edge[i].to; 48 if (v==son[x]||v==pa) continue; 49 dfs2(v,x,v); 50 } 51 } 52 void pushdown(int rt,int l,int r) 53 { 54 int mid=(l+r)/2; 55 if (lazy[rt]) 56 { 57 int ls=rt<<1,rs=ls+1; 58 c[ls]+=s[ls]*lazy[rt]; 59 lazy[ls]+=lazy[rt]; 60 mx[ls]+=lazy[rt]; 61 c[rs]+=s[rs]*lazy[rt]; 62 lazy[rs]+=lazy[rt]; 63 mx[rs]+=lazy[rt]; 64 lazy[rt]=0; 65 } 66 } 67 void pushup(int rt) 68 { 69 mx[rt]=max(mx[rt<<1],mx[rt<<1|1]); 70 c[rt]=c[rt<<1]+c[rt<<1|1]; 71 } 72 void build(int rt,int l,int r) 73 { 74 if (l==r) 75 { 76 s[rt]=dep[id[l]]-dep[fa[id[l]]]; 77 return; 78 } 79 int mid=(l+r)/2; 80 build(rt<<1,l,mid); 81 build(rt<<1|1,mid+1,r); 82 s[rt]=s[rt<<1]+s[rt<<1|1]; 83 } 84 void update(int rt,int l,int r,int L,int R,lol d) 85 { 86 if (l>=L&&r<=R) 87 { 88 c[rt]+=s[rt]*d; 89 lazy[rt]+=d; 90 mx[rt]+=d; 91 return; 92 } 93 int mid=(l+r)/2; 94 pushdown(rt,l,r); 95 if (L<=mid) update(rt<<1,l,mid,L,R,d); 96 if (R>mid) update(rt<<1|1,mid+1,r,L,R,d); 97 pushup(rt); 98 } 99 lol query(int rt,int l,int r,int L,int R) 100 { 101 if (l>=L&&r<=R) 102 { 103 return c[rt]; 104 } 105 int mid=(l+r)/2; 106 lol sum=0; 107 pushdown(rt,l,r); 108 if (L<=mid) sum+=query(rt<<1,l,mid,L,R); 109 if (R>mid) sum+=query(rt<<1|1,mid+1,r,L,R); 110 pushup(rt); 111 return sum; 112 } 113 void change(int x,lol d) 114 { 115 while (x) 116 { 117 update(1,1,n,dfn[top[x]],dfn[x],d); 118 x=fa[top[x]]; 119 } 120 } 121 lol ask(int x) 122 { 123 lol sum=0; 124 while (x) 125 { 126 sum+=query(1,1,n,dfn[top[x]],dfn[x]); 127 x=fa[top[x]]; 128 } 129 return sum; 130 } 131 int take(int rt,int l,int r,int x) 132 { 133 if (l==r) return l; 134 int mid=(l+r)/2; 135 pushdown(rt,l,r); 136 if (mx[rt<<1|1]>=x) return take(rt<<1|1,mid+1,r,x); 137 return take(rt<<1,l,mid,x); 138 } 139 int find(int x) 140 { 141 return take(1,1,n,x); 142 } 143 int main() 144 {int i,u,v,x; 145 lol w,sx,e; 146 cin>>n>>Q; 147 for (i=1;i<=n-1;i++) 148 { 149 scanf("%d%d%lld",&u,&v,&w); 150 add(u,v,w);add(v,u,w); 151 } 152 dfs1(1,0); 153 dfs2(1,0,1); 154 build(1,1,n); 155 w=0; 156 sx=0; 157 while (Q--) 158 { 159 scanf("%d%lld",&u,&e); 160 change(u,e); 161 sx+=dep[u]*e; 162 w+=e; 163 x=id[find(w+1>>1)]; 164 printf("%lld\n",sx+w*dep[x]-2*ask(x)); 165 } 166 }