题解 数据结构

传送门

所以 yyl 是谁啊

正解比较神仙:
发现这个带权重心的子树和一定 \(\geqslant \frac{sum}{2}\)
因为要找深度最小的所以一定 \(>\frac{sum}{2}\)
那么如果我们能确定某个点在这个重心的子树中
那重心就是这个点到根的路径上第一个子树和 \(>\frac{sum}{2}\) 的点,那么就可以倍增了
那这样的点怎么找呢?

  • 一棵带权树的 dfs 序列的带权中点一定在这棵树的带权重心的子树中
    证明:因为重心的子树和 \(>\frac{sum}{2}\),而 dfs 序的带权中点左右两边的和都 \(\leqslant \frac{sum}{2}\)
    那么这个带权中点一定在重心子树中

需要用树状数组卡常,复杂度 \(O(n\log^2 n)\)

点击查看代码
#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;
}
posted @ 2022-03-20 17:49  Administrator-09  阅读(3)  评论(0编辑  收藏  举报