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 }

 

posted @ 2025-07-24 19:51  KLaneX  阅读(21)  评论(0)    收藏  举报