题解 数据结构
所以 yyl 是谁啊
正解比较神仙:
发现这个带权重心的子树和一定
因为要找深度最小的所以一定
那么如果我们能确定某个点在这个重心的子树中
那重心就是这个点到根的路径上第一个子树和 的点,那么就可以倍增了
那这样的点怎么找呢?
- 一棵带权树的 dfs 序列的带权中点一定在这棵树的带权重心的子树中
证明:因为重心的子树和 ,而 dfs 序的带权中点左右两边的和都
那么这个带权中点一定在重心子树中
需要用树状数组卡常,复杂度
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define N 300010
#define fir first
#define sec second
#define ll long long
#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, q;
int head[N], dep[N], back[N], ecnt;
struct edge{int to, next;}e[N<<1];
inline void add(int s, int t) {e[++ecnt]={t, head[s]}; head[s]=ecnt;}
void dfs1(int u, int fa) {
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (v==fa) continue;
dep[v]=dep[u]+1;
back[v]=u;
dfs1(v, u);
}
}
// namespace force{
// int val[N];
// pair<int, int> fir[N], sec[N], rot;
// void dfs2(int u, int fa) {
// fir[u]={0, u}; sec[u]={0, u};
// for (int i=head[u],v; ~i; i=e[i].next) {
// v = e[i].to;
// if (v==fa) continue;
// dfs2(v, u);
// if (fir[v].fir+val[v]>fir[u].fir) sec[u]=fir[u], fir[u]={fir[v].fir+val[v], v};
// else if (fir[v].fir+val[v]>sec[u].fir) sec[u]={fir[v].fir+val[v], v};
// }
// }
// void dfs3(int u, int fa, pair<int, int> g) {
// if (g.fir>fir[u].fir) sec[u]=fir[u], fir[u]=g;
// else if (g.fir>sec[u].fir) sec[u]=g;
// if (fir[u].fir<rot.fir) rot={fir[u].fir, u};
// else if (fir[u].fir==rot.fir && dep[u]<dep[rot.sec]) rot={fir[u].fir, u};
// for (int i=head[u],v; ~i; i=e[i].next) {
// v = e[i].to;
// if (v==fa) continue;
// if (v==fir[u].sec) dfs3(v, u, {sec[u].fir+val[u], sec[u].sec});
// else dfs3(v, u, {fir[u].fir+val[u], fir[u].sec});
// }
// }
// void add(int u, int fa, int w) {
// val[u]+=w;
// for (int i=head[u],v; ~i; i=e[i].next) {
// v = e[i].to;
// if (v==fa) continue;
// add(v, u, w);
// }
// }
// void rebuild() {rot={INF, 0}; dfs2(1, 0); dfs3(1, 0, {0, 0});}
// void solve() {
// for (int i=1,u,v,x,w; i<=q; ++i) {
// cout<<"i: "<<i<<endl;
// if (read()&1) {
// x=read(); w=read();
// add(x, back[x], w);
// rebuild();
// printf("%lld\n", rot.sec);
// }
// else {
// u=read(); v=read(); w=read();
// while (1) {
// if (dep[u]<dep[v]) swap(u, v);
// val[u]+=w;
// if (u==v) break;
// else u=back[u];
// }
// rebuild();
// printf("%lld\n", rot.sec);
// }
// cout<<"fir: "; for (int j=1; j<=n; ++j) cout<<fir[j].fir<<' '; cout<<endl;
// cout<<"val: "; for (int j=1; j<=n; ++j) cout<<val[j]<<' '; cout<<endl;
// }
// }
// }
namespace force{
int val[N], sum[N];
pair<int, int> fir[N], sec[N], rot;
void dfs2(int u, int fa) {
sum[u]=val[u];
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (v==fa) continue;
dfs2(v, u);
sum[u]+=sum[v];
}
}
void dfs3(int u, int fa) {
ll maxn=sum[1]-sum[u];
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (v==fa) continue;
dfs3(v, u);
maxn=max(maxn, sum[v]);
}
if (maxn<rot.fir) rot={maxn, u};
else if (maxn==rot.fir && dep[u]<dep[rot.sec]) rot={maxn, u};
}
void add(int u, int fa, int w) {
val[u]+=w;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (v==fa) continue;
add(v, u, w);
}
}
void rebuild() {rot={INF, 0}; dfs2(1, 0); dfs3(1, 0);}
void solve() {
for (int i=1,u,v,x,w; i<=q; ++i) {
// cout<<"i: "<<i<<endl;
if (read()&1) {
x=read(); w=read();
add(x, back[x], w);
rebuild();
printf("%lld\n", rot.sec);
}
else {
u=read(); v=read(); w=read();
while (1) {
if (dep[u]<dep[v]) swap(u, v);
val[u]+=w;
if (u==v) break;
else u=back[u];
}
rebuild();
printf("%lld\n", rot.sec);
}
// cout<<"fir: "; for (int j=1; j<=n; ++j) cout<<fir[j].fir<<' '; cout<<endl;
// cout<<"val: "; for (int j=1; j<=n; ++j) cout<<val[j]<<' '; cout<<endl;
}
}
}
namespace task{
int bit1[N], bit2[N], lg[N], fa[24][N];
int id[N], rk[N], siz[N], msiz[N], mson[N], top[N], tot, sum;
void dfs2(int u, int pa) {
siz[u]=1;
for (int i=1; i<24; ++i)
if (dep[u]>=1<<i) fa[i][u]=fa[i-1][fa[i-1][u]];
else break;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (v==pa) continue;
fa[0][v]=u;
dfs2(v, u);
siz[u]+=siz[v];
if (siz[v]>msiz[u]) msiz[u]=siz[v], mson[u]=v;
}
}
void dfs3(int u, int fa, int t) {
top[u]=t;
rk[id[u]=++tot]=u;
if (!mson[u]) return ;
dfs3(mson[u], u, t);
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (v==fa || v==mson[u]) continue;
dfs3(v, u, v);
}
}
inline void upd1(int i, int dat) {for (; i<=n; i+=i&-i) bit1[i]+=dat;}
inline void upd2(int i, int dat) {dat*=i; for (; i<=n; i+=i&-i) bit2[i]+=dat;}
inline int query1(int i) {int ans=0; for (; i; i-=i&-i) ans+=bit1[i]; return ans;}
inline int query2(int i) {int ans=0; for (; i; i-=i&-i) ans+=bit2[i]; return ans;}
inline void add(int l, int r, int w) {upd1(l, w); upd2(l, w); upd1(r+1, -w); upd2(r+1, -w);}
inline int query(int l, int r) {return ((r+1)*query1(r)-query2(r)) - (l*query1(l-1)-query2(l-1));}
void upd(int u, int v, int w) {
while (top[u]!=top[v]) {
if (dep[top[u]]<dep[top[v]]) swap(u, v);
add(id[top[u]], id[u], w);
sum+=w*(id[u]-id[top[u]]+1);
u=back[top[u]];
}
if (dep[u]>dep[v]) swap(u, v);
add(id[u], id[v], w);
sum+=w*(id[v]-id[u]+1);
}
int query() {
// cout<<"query: "; for (int i=1; i<=n; ++i) cout<<query(i, i)<<' '; cout<<endl;
int l=1, r=n, mid;
while (l<=r) {
mid=(l+r)>>1;
if (query(1, mid)*2<sum) l=mid+1;
else r=mid-1;
}
// cout<<"l: "<<l<<endl;
mid=rk[l];
// cout<<"mid: "<<mid<<endl;
for (int i=lg[dep[mid]]-1,t; ~i; --i) {
t=fa[i][mid];
if (t && query(id[t], id[t]+siz[t]-1)*2<=sum) mid=t;
}
if (query(id[mid], id[mid]+siz[mid]-1)*2<=sum) mid=fa[0][mid];
// cout<<"rot: "<<mid<<endl;
return mid;
}
void solve() {
dfs2(1, 0); dfs3(1, 0, 1);
for (int i=1; i<=n; ++i) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
for (int i=1,u,v,x,w; i<=q; ++i) {
if (read()&1) {
x=read(); w=read();
add(id[x], id[x]+siz[x]-1, w);
sum+=w*siz[x];
printf("%lld\n", query());
}
else {
u=read(); v=read(); w=read();
upd(u, v, w);
printf("%lld\n", query());
}
}
}
}
signed main()
{
freopen("yyl.in", "r", stdin);
freopen("yyl.out", "w", stdout);
n=read();
memset(head, -1, sizeof(head));
for (int i=1,u,v; i<n; ++i) {
u=read(); v=read();
add(u, v); add(v, u);
}
dep[1]=1; dfs1(1, 0);
q=read();
// force::solve();
task::solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通