P3345 [ZJOI2015] 幻想乡战略游戏
P3345
没啥好说的,约等同于模板的树剖&线段树
关键在于找重心
重心跟点权相关
然后进行树上二分就ok了
查询和修改的复杂度都是O(n log^2 n)级别的
对于洛谷给定的每个test点6s的时间限制来说绰绰有余
AC Code:
1 // Problem: P3345 [ZJOI2015] 幻想乡战略游戏 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/P3345 4 // Memory Limit: 250 MB 5 // Time Limit: 6000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 //线段树+树剖板子题 9 #include<bits/stdc++.h> 10 #define int long long 11 #define endl '\n' 12 #define endll " " 13 #define it inline int 14 #define fre(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout); 15 #pragma GCC optimize(0) 16 #pragma GCC optimize(2) 17 #pragma GCC optimize(3,"Ofast","inline") 18 using namespace std; 19 const int MAXN=500050; 20 const int INF=0x3f3f3f3f; 21 it gcd(int x,int y){return y==0?x:gcd(y,x%y);} 22 it lcm(int x,int y){return x/gcd(x,y)*y;} 23 it max(int x,int y){return x>y?x:y;} 24 it min(int x,int y){return x<y?x:y;} 25 it qpow(int x,int m,int mod) 26 { 27 int res=1,bas=x%mod; 28 while(m) 29 { 30 if(m&1) res=(res*bas)%mod; 31 bas=(bas*bas)%mod,m>>=1; 32 } 33 return res%mod; 34 } 35 int n,m,u,v,w,l,r,ans,cnt,sum,tot,num,head[MAXN],dfn[MAXN],lazy[MAXN],wi[MAXN],rt; 36 int fa[MAXN],dep[MAXN],top[MAXN],wh[MAXN],son[MAXN],id[MAXN],sz[MAXN],dis[MAXN]; 37 int tanda,hazuki; 38 struct edge 39 { 40 int to,nxt,w; 41 }e[MAXN]; 42 struct tree 43 { 44 int siz,val,sum; 45 }t[MAXN*4]; 46 void add_edge(int u,int v,int w) 47 { 48 e[++tot].to=v; 49 e[tot].nxt=head[u]; 50 e[tot].w=w; 51 head[u]=tot; 52 } 53 void dfs1(int u) 54 { 55 for(int i=head[u];i;i=e[i].nxt) 56 { 57 int v=e[i].to; 58 if(v!=fa[u]) 59 { 60 fa[v]=u; 61 dep[v]=dep[u]+1; 62 dis[v]=dis[u]+e[i].w; 63 sz[v]=1; 64 dfs1(v); 65 if(sz[son[u]]<sz[v]) 66 son[u]=v; 67 sz[u]+=sz[v]; 68 } 69 } 70 } 71 void dfs2(int u,int f) 72 { 73 top[u]=f; 74 id[u]=++cnt; 75 wh[cnt]=u; 76 wi[cnt]=dis[u]-dis[fa[u]]; 77 if(son[u]) 78 { 79 dfs2(son[u],f); 80 for(int i=head[u];i;i=e[i].nxt) 81 { 82 int v=e[i].to; 83 if(v!=fa[u]&&v!=son[u]) 84 dfs2(v,v); 85 } 86 } 87 } 88 void pushup(int i) 89 { 90 t[i].siz=max(t[i*2].siz,t[i*2+1].siz); 91 t[i].sum=t[i*2].sum+t[i*2+1].sum; 92 } 93 void pushdown(int i) 94 { 95 if(lazy[i]) 96 { 97 t[i*2].siz+=lazy[i]; 98 t[i*2+1].siz+=lazy[i]; 99 lazy[i*2]+=lazy[i]; 100 lazy[i*2+1]+=lazy[i]; 101 t[i*2].sum+=lazy[i]*t[i*2].val; 102 t[i*2+1].sum+=lazy[i]*t[i*2+1].val; 103 lazy[i]=0; 104 } 105 } 106 void build(int i,int l,int r) 107 { 108 if(l==r) 109 { 110 t[i].val=wi[l]; 111 return; 112 } 113 int mid=(l+r) >> 1; 114 build(i*2,l,mid); 115 build(i*2+1,mid+1,r); 116 t[i].val=t[i*2].val+t[i*2+1].val; 117 } 118 void modify(int i,int l,int r,int ql,int qr,int val) 119 { 120 if(l>=ql && r<=qr) 121 { 122 t[i].siz+=val; 123 t[i].sum+=val*t[i].val; 124 lazy[i]+=val; 125 return; 126 } 127 pushdown(i); 128 int mid=(l+r) >> 1; 129 if(ql<=mid) 130 modify(i*2,l,mid,ql,qr,val); 131 if(qr>mid) 132 modify(i*2+1,mid+1,r,ql,qr,val); 133 pushup(i); 134 } 135 it query(int i,int l,int r,int ql,int qr) 136 { 137 if(l>=ql && r<=qr) 138 { 139 return t[i].sum; 140 } 141 pushdown(i); 142 int mid=(l+r) >> 1; 143 int res=0; 144 if(ql<=mid) 145 res+=query(i*2,l,mid,ql,qr); 146 if(qr>mid) 147 res+=query(i*2+1,mid+1,r,ql,qr); 148 return res; 149 } 150 it find_root() 151 { 152 int i=1,l=1,r=n; 153 while(l<r) 154 { 155 pushdown(i); 156 int mid=(l+r) >> 1; 157 if(t[i*2+1].siz*2>=t[1].siz) 158 { 159 l=mid+1; 160 i=i*2+1; 161 } 162 else 163 { 164 r=mid; 165 i=i*2; 166 } 167 } 168 return wh[l]; 169 } 170 void exmodify(int u,int v) 171 { 172 while(top[u]!=1) 173 { 174 modify(1,1,n,id[top[u]],id[u],v); 175 u=fa[top[u]]; 176 } 177 modify(1,1,n,1,id[u],v); 178 } 179 it exquery(int u) 180 { 181 int res=0; 182 while(top[u]!=1) 183 { 184 res+=query(1,1,n,id[top[u]],id[u]); 185 u=fa[top[u]]; 186 } 187 return res+query(1,1,n,1,id[u]); 188 } 189 signed main() 190 { 191 //fre("P3345"); 192 ios::sync_with_stdio(false); 193 cin.tie(0); 194 cout.tie(0); 195 cin >> n >> m; 196 for(int i=1;i<n;i++) 197 { 198 cin >> u >> v >> w; 199 add_edge(u,v,w); 200 add_edge(v,u,w); 201 } 202 dfs1(1); 203 dfs2(1,1); 204 build(1,1,n); 205 for(int i=1;i<=m;i++) 206 { 207 cin >> u >> v; 208 tanda+=v; 209 hazuki+=dis[u]*v; 210 exmodify(u,v); 211 int rt=find_root(); 212 cout<<dis[rt]*tanda+hazuki-2*exquery(rt)<<endl; 213 } 214 return 0; 215 }

浙公网安备 33010602011771号