BZOJ3924: [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
Output
对于幽香的每个操作,输出操作完成以后,每天的最小花费,也即如果幽香选择最优的补给点进行补给时的花费。
Sample Input
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
Sample Output
1
4
5
6
解题思路:
相当于动态统计一棵树的带权重心。
怎么搞呢?
序列上会不会。
不就是二分吗,这东西会形成一个单峰函数。
证明我不会不过可以拿这个代码看一下。
#include<cstdio> #include<algorithm> typedef long long lnt; const int N=10; int a[]={0,101,2131,321,432,213,3124,5342,2323,5432,2323, 122,2511,321,432,2513,3132,5342,2323,5432,2323, 102,211,321,432,2133,3124,5342,2323,5432,2323, 12,2131,321,43124,52323,5432,2323, 102,231,21,43413224,5342,323,5432,3, 153,2131,213213,3124,5342,2323,543323, 102,21,321,43242,233,5432,2323, 502,2131,321,4,5342,2323,5432,2323 102,2131,321,53,2323,5432,2323, 12302,2131,3212,432,122342,2323,5432,2323, 103212,2131,321,432,21324,5312,28323,5432,23 1102,2131,321,432,213,3124,5342,2323,5432,3, 1023,2131,321,432,213,31124,5342,2323,543223, 103212,2131,321,432,213,3124,5342,2323,5432,3, 102,2131,321,432,5213,3124,5342,2323,5432,2323, 102,2131,321,432,213,3124,5342,2323,5432,2323,}; lnt fan(int pos) { lnt ans=0; for(int i=1;i<=N;i++) { ans+=1ll*std::abs(pos-i)*a[i]; } return ans; } int main() { for(int i=1;i<=N;i++) printf("%I64d ",fan(i)); return 0; }
所以就是单峰了。
所以说就可以在树上做同样的试探动作。
如果一个点的答案更优秀那么答案就在其子树中。
可以知道一个点答案就是向父亲走时加入容斥。
那个公式我就不推了QAQ。
维护三个答案,子到父代价,子树代价,子树全职和。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 typedef long long lnt; 5 const int N=100010; 6 struct pnt{ 7 int fa; 8 int hd; 9 int hf; 10 int dp; 11 int wgt; 12 int ind; 13 lnt dis; 14 lnt sum; 15 lnt diss; 16 lnt disf; 17 bool vis; 18 }p[N]; 19 struct ent{ 20 int twd; 21 int lst; 22 lnt vls; 23 }e[N<<2]; 24 int rt; 25 int n,m; 26 int cnt; 27 int dfn; 28 int root; 29 int size; 30 int maxsize; 31 int lg[N<<2]; 32 int eula[N<<2][21]; 33 void ade(int f,int t,lnt v) 34 { 35 cnt++; 36 e[cnt].twd=t; 37 e[cnt].vls=v; 38 e[cnt].lst=p[f].hd; 39 p[f].hd=cnt; 40 return ; 41 } 42 void adf(int f,int t,int lin) 43 { 44 cnt++; 45 e[cnt].twd=t; 46 e[cnt].vls=lin; 47 e[cnt].lst=p[f].hf; 48 p[f].hf=cnt; 49 return ; 50 } 51 void E_dfs(int x,int f) 52 { 53 eula[++dfn][0]=x; 54 p[x].ind=dfn; 55 p[x].dp=p[f].dp+1; 56 for(int i=p[x].hd;i;i=e[i].lst) 57 { 58 int to=e[i].twd; 59 if(to==f) 60 continue; 61 p[to].dis=p[x].dis+e[i].vls; 62 E_dfs(to,x); 63 eula[++dfn][0]=x; 64 } 65 return ; 66 } 67 int Emin(int x,int y) 68 { 69 return p[x].dp<p[y].dp?x:y; 70 } 71 int Lca(int x,int y) 72 { 73 x=p[x].ind; 74 y=p[y].ind; 75 if(x>y) 76 std::swap(x,y); 77 int l=lg[y-x+1]; 78 return Emin(eula[x][l],eula[y-(1<<l)+1][l]); 79 } 80 lnt Dis(int x,int y) 81 { 82 int z=Lca(x,y); 83 return p[x].dis+p[y].dis-2*p[z].dis; 84 } 85 void grc_dfs(int x,int f) 86 { 87 p[x].wgt=1; 88 int maxs=-1; 89 for(int i=p[x].hd;i;i=e[i].lst) 90 { 91 int to=e[i].twd; 92 if(to==f||p[to].vis) 93 continue; 94 grc_dfs(to,x); 95 p[x].wgt+=p[to].wgt; 96 if(p[to].wgt>maxs) 97 maxs=p[to].wgt; 98 } 99 maxs=std::max(maxs,size-p[x].wgt); 100 if(maxs<maxsize) 101 { 102 maxsize=maxs; 103 root=x; 104 } 105 return ; 106 } 107 void bin_dfs(int x,int f) 108 { 109 p[x].fa=f; 110 p[x].vis=true; 111 int tmp=size; 112 for(int i=p[x].hd;i;i=e[i].lst) 113 { 114 int to=e[i].twd; 115 if(p[to].vis) 116 continue; 117 root=0; 118 if(p[x].wgt<p[to].wgt) 119 size=tmp-p[x].wgt; 120 else 121 size=p[to].wgt; 122 maxsize=0x3f3f3f3f; 123 grc_dfs(to,to); 124 adf(x,root,to); 125 bin_dfs(root,x); 126 } 127 return ; 128 } 129 void update(int x,lnt y) 130 { 131 p[x].sum+=y; 132 for(int i=x;p[i].fa;i=p[i].fa) 133 { 134 p[p[i].fa].sum+=y; 135 lnt tmp=Dis(x,p[i].fa)*y; 136 p[i].disf+=tmp; 137 p[p[i].fa].diss+=tmp; 138 } 139 return ; 140 } 141 lnt assess(int x) 142 { 143 lnt ans=p[x].diss; 144 for(int i=x;p[i].fa;i=p[i].fa) 145 { 146 lnt tmp=Dis(x,p[i].fa); 147 ans+=tmp*(p[p[i].fa].sum-p[i].sum); 148 ans+=p[p[i].fa].diss-p[i].disf; 149 } 150 return ans; 151 } 152 lnt Query(void) 153 { 154 bool has=true; 155 lnt ans=assess(rt); 156 int lastpos=rt; 157 while(has) 158 { 159 has=false; 160 for(int i=p[lastpos].hf;i;i=e[i].lst) 161 { 162 int to=e[i].twd; 163 lnt tmp=assess(e[i].vls); 164 if(tmp<ans) 165 { 166 has=true; 167 ans=assess(to); 168 lastpos=to; 169 break; 170 } 171 } 172 } 173 return ans; 174 } 175 int main() 176 { 177 scanf("%d%d",&n,&m); 178 for(int i=1;i<n;i++) 179 { 180 int a,b; 181 lnt c; 182 scanf("%d%d%lld",&a,&b,&c); 183 ade(a,b,c); 184 ade(b,a,c); 185 } 186 E_dfs(1,1); 187 for(int i=2;i<=dfn;i++) 188 lg[i]=lg[i>>1]+1; 189 for(int i=1;i<=20;i++) 190 for(int j=1;j+(1<<i)-1<=dfn;j++) 191 eula[j][i]=Emin(eula[j][i-1],eula[j+(1<<(i-1))][i-1]); 192 root=0; 193 size=n; 194 maxsize=0x3f3f3f3f; 195 grc_dfs(1,1); 196 rt=root; 197 bin_dfs(root,0); 198 while(m--) 199 { 200 int x,y; 201 scanf("%d%d",&x,&y); 202 update(x,y); 203 printf("%lld\n",Query()); 204 } 205 return 0; 206 }