蒟蒻刚学树剖一坤秒,样例过但全WA求调qwq
查看原帖
蒟蒻刚学树剖一坤秒,样例过但全WA求调qwq
606080
Dr_Einzbern楼主2023/8/18 18:23
#include <bits/stdc++.h>
#define mid ((l+r)/2)
#define ll long long
using namespace std;
const ll N = 1e6+5, INF = 0x3f3f3f3f;
using namespace std;
ll w[N], wnew[N];

//-----------------------线段树 
ll sumn[N<<2], tag[N<<2], maxn[N<<2];
ll ls(ll p) {return p << 1;}
ll rs(ll p) {return p << 1 | 1;}

void push_up(ll p){
	sumn[p] = sumn[ls(p)] + sumn[rs(p)];
	maxn[p] = max(maxn[ls(p)], maxn[rs(p)]);
}
void build(ll p, ll l, ll r){
	tag[p] = 0;
	if(l == r){
		sumn[p] = wnew[l];
		maxn[p] = wnew[l];
		return;
	}
	build(ls(p), l, mid);
	build(rs(p), mid+1, r);
	push_up(p);
}
void addtag(ll p, ll l, ll r, ll d){
	tag[p] = d;
	sumn[p] = (d * (r-l+1));
	maxn[p] = (d * (r-l+1));
}
void push_down(ll p, ll l, ll r){
	if(tag[p]){
		addtag(ls(p), l, mid, tag[p]);
		addtag(rs(p), mid+1, r, tag[p]);
		tag[p] = 0;
	}
}

void update(ll pl, ll pr, ll p, ll l, ll r, ll d){
	if(pl <= l && r <= pr)
	{
		addtag(p, l, r, d);
		return;
	}
	push_down(p, l, r);
	if(pl <= mid) update(pl, pr, ls(p), l, mid, d);
	if(pr > mid)  update(pl, pr, rs(p), mid+1, r, d);
	push_up(p);
}
ll query_max(ll pl, ll pr, ll p, ll l, ll r){ //query(pl, pr)
	if(pl <= l && r <= pr) return maxn[p];
	push_down(p, l, r);
	ll res = -INF;
	if(pl <= mid) res = max(res, query_max(pl, pr, ls(p), l, mid));
	if(pr > mid)  res = max(res, query_max(pl, pr, rs(p), mid+1, r));
	return res;
}
ll query_sum(ll pl, ll pr, ll p, ll l, ll r){ //query(pl, pr)
	if(pl <= l && r <= pr) return sumn[p];
	push_down(p, l, r);
	ll res = 0;
	if(pl <= mid) res += query_sum(pl, pr, ls(p), l, mid);
	if(pr > mid)  res += query_sum(pl, pr, rs(p), mid+1, r);
	return res;
}

//-----------------------树链剖分  
vector<ll> g[N];
ll depth[N], si[N], son[N], top[N], father[N];
//深度, 子节点数, 重子, 链头, 父节点
ll n, m, s, a, b;
void dfs1(ll u, ll fa){ //求重子
	depth[u] = depth[fa] + 1;
	father[u] = fa;
	si[u] = 1;
	for(auto v : g[u]){
		if(v != fa){
			father[v] = u;
			dfs1(v, u);
			si[u] += si[v];
			if(!son[u] || si[son[u]] < si[v]){
				son[u] = v;
			}
		}
	}
}
ll dfn[N];
ll num = 0;
void dfs2(ll u, ll topu){ //建树剖
	dfn[u] = ++num;
	wnew[num] = w[u];
	top[u] = topu;
	if(!son[u]) return;
	dfs2(son[u], topu);
	for(auto v : g[u]){
		if(v != father[u] && v != son[u]){
			dfs2(v, v);
		}	
	}	
}

//-----------------------conbination
void update_range(ll x, ll y, ll z){
	while(top[x] != top[y]){
		if(depth[top[x]] < depth[top[y]]) swap(x, y);
		update(dfn[top[x]], dfn[x], 1, 1, n, z);
		x = father[top[x]];
	}
	if(depth[x] > depth[y]) swap(x, y);
	update(dfn[x], dfn[y], 1, 1, n, z);
}
ll query_range_max(ll x, ll y){
	ll ans = -INF;
	while(top[x] != top[y]){
		if(depth[top[x]] < depth[top[y]]) swap(x, y);
		ans = max(ans, query_max(dfn[top[x]], dfn[x], 1, 1, n));
		x = father[top[x]];
	}
	if(depth[x] > depth[y]) swap(x, y);
	ans = max(ans, query_max(dfn[x], dfn[y], 1, 1, n));
    return ans;
}
ll query_range_sum(ll x, ll y){ //同上
	ll ans = 0;
	while(top[x] != top[y]){
		if(depth[top[x]] < depth[top[y]]) swap(x, y);
		ans += query_sum(dfn[top[x]], dfn[x], 1, 1, n);
		x = father[top[x]];
	}
	if(depth[x] > depth[y]) swap(x, y);
	ans += query_sum(dfn[x], dfn[y], 1, 1, n);
	return ans;
}
//-----------------------快乐的主函数 
int main(){
	memset(maxn, -0x3f, sizeof(maxn));
	cin >> n;
	for(ll i = 1; i < n; i++){
		scanf("%lld %lld", &a, &b);
		g[a].push_back(b);
		g[b].push_back(a);
	}
	for(ll i = 1; i <= n; i++){
		scanf("%lld", &w[i]);
	}
	dfs1(1, 0);
	dfs2(1, 1);
	build(1, 1, n);
    cin >> m;
	ll x, y, z;
    string k;
	while(m--){
		cin >> k;
		if(k == "CHANGE")    {scanf("%lld%lld", &x, &z); update_range(x, x, z);}
		else if(k == "QMAX") {scanf("%lld%lld", &x, &y); printf("%lld\n", query_range_max(x, y));}
        else                 {scanf("%lld%lld", &x, &y); printf("%lld\n", query_range_sum(x, y));}
	}
	return 0;
}

从 P3384 【模板】重链剖分/树链剖分 来的,仍是沿用的区间修改,但主观认为没有影响……或许罢()

2023/8/18 18:23
加载中...