树剖+set(动态维护树上直径(形态不变,点权变)):0103A

http://cplusoj.com/d/senior/p/SS20240103A

在这里插入图片描述

显然可以点分树,然后被卡空间


任何一条树上的链都可以这样表示:

在这里插入图片描述

因此我们可以把所有轻儿子挂在重链上,然后求重链的最大子段和

因为我们要支持删除,同时树上每个节点要求连出去轻儿子中的最大,因此我们树上每个节点拿个set维护所有轻儿子

pre coding at 14:46
st coding at 15:09
st bugging at 17:08
passing at 20:27
fn blogging at 20:39
// 7.2k
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
 #define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
 #define debug(...) void(0)
#endif
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define fi first
#define se second
//#define M
//#define mo
#define N 1000010
int n, m, i, j, k, T;
multiset<int>ans_set; 
int dep[N], a[N], F[N], w[N], top[N], Ed[N], son[N], tot, u, v; 
int dfn[N], q, op, dfn_xu[N]; 
vector<int>G[N]; 

struct Segment_tree {
	#define ls (k<<1)
	#define rs (k<<1|1)
	#define mid ((l+r)>>1)
	struct node {
		int s, L, R, mx; 
		void mem() { s = L = R = mx = 0; }
		node operator + (const node &a) const {
			node b; b.mem(); 
			b.s = s + a.s;  
			b.L = max(L, s + a.L); 
			b.R = max(a.R, R + a.s); 
			b.mx = max({mx, a.mx, R + a.L});
			return b;  
		}
	}a[N<<2];
	multiset<int>s[N<<2]; 
	void push_up(int k) {
		a[k] = a[ls] + a[rs]; 
	}
	void build(int k, int l, int r, int *A) {
		if(l == r) {
			a[k].s = a[k].mx = a[k].L = a[k].R = A[dfn_xu[l]]; s[k].insert(0); 
//			debug("[%lld] : %lld | %lld\n", l, a[k].mx, A[dfn_xu[l]]); 
			return ; 
		}
		build(ls, l, mid, A); build(rs, mid+1, r, A); 
		push_up(k); 
	}
	void add(int k, int l, int r, int x, int y) {
		assert(x >= 1 && x <= n); 
		if(l == r) {
			a[k].s = y; auto t = s[k].end(); --t; 
			a[k].L = a[k].R = a[k].mx = y + (*t); 
			if(s[k].size() >= 2) { --t; a[k].mx += max(0ll, (*t)); }
//			debug("So a[k[%lld]].s = %lld | mx = %lld\n", l, a[k].s, a[k].mx);
			return ; 
		}
		if(x <= mid) add(ls, l, mid, x, y); 
		else add(rs, mid + 1, r, x, y); 
		push_up(k); 
	}
	void update(int k, int l, int r, int x, int y, int o) {
		assert(x >= 1 && x <= n); 
		assert(k > 0 && k <= 4*n); 
		assert(l <= r && l >= 1 && r <= n); 
		assert(y <= 1e18); 
//		if(q == 80769) debug("[%lld] [%lld %lld] %lld => %lld | %lld\n", k, l, r, x, y, o); 
		if(l == r) { 
			if(k == 215325) debug("%lld [%lld] || %d\n", y, o, s[k].size()); 
			if(o == 1) s[k].insert(y);
			else {
				if(s[k].find(y) == s[k].end()) debug("fdsfdasfadfasd\n"); 
				s[k].erase(s[k].find(y)); 
			}
			if(k == 215325) debug("%lld [%lld] || %d\n", y, o, s[k].size()); 
			assert(!s[k].empty()); 
			auto t = s[k].end(); --t; 
			a[k].L = a[k].R = a[k].mx = a[k].s + (*t); 
//			debuug("upd")
//			debug("		%lld : %lld | %lld\n", x, a[k].mx, (*t)); 
//			debug("%lld : %lld\n", k, s[k].size()); 
//			debug("%lld [%lld] %lld | s %lld %lld\n", k, dfn_xu[k], (*t), a[k].s, a[k].mx); 
			if(t != s[k].begin()) { 
				/* debug("? %lld [%lld]\n", l, dfn_xu[l]); */ 
				--t; a[k].mx += max(0ll, (*t)); 
//				debug("\t\t next %lld === %lld\n", *t, a[k].mx); 
			}
			return ; 
		}
		if(x <= mid) update(ls, l, mid, x, y, o); 
		else update(rs, mid+1, r, x, y, o); 
		push_up(k); 
	}
	node quemx(int k, int l, int r, int x, int y) {
		assert(x >= 1 && x <= n); 
		assert(y >= 1 && y <= n); 
		if(l >= x && r <= y) return a[k]; 
		node a, b; a.mem(); b.mem(); 
		if(x <= mid) a = quemx(ls, l, mid, x, y); else return quemx(rs, mid+1, r, x, y); 
		if(y >= mid+1) b = quemx(rs, mid+1, r, x, y); else return a; 
		return a + b; 
	}
	pair<int, int> queRmx(int k, int l, int r, int x, int y) {
		assert(x >= 1 && x <= n); 
		assert(y >= 1 && y <= n); 
		if(l >= x && r <= y) return {a[k].s, a[k].L}; 
		pair<int, int> ta, tb, t; 
		if(x <= mid) ta = queRmx(ls, l, mid, x, y); 
		else return queRmx(rs, mid + 1, r, x, y); 
		if(y >= mid + 1) tb = queRmx(rs, mid + 1, r, x, y); 
		else return ta; 
		return {ta.fi + tb.fi, max(ta.se, ta.fi + tb.se)}; 
	}
	#undef ls
	#undef rs
	#undef mid
}Seg;

namespace Tree {
	void dfs(int x, int fa) {
		dep[x] = dep[fa] + a[x]; w[x] = 1; F[x] = fa; 
		for(int y : G[x]) if(y != fa) {
			dfs(y, x); w[x] += w[y]; 
			debug("%d : %d | %lld")
			if(w[y] > w[son[x]]) son[x] = y; 
		}
//		debug("%lld : %lld\n", x, son[x]); 
	}
	int dfs2(int x, int fa, int Top) {
		top[x] = Top; dfn[x] = ++tot; Ed[x] = x; dfn_xu[tot] = x; 
//		debug("%d ", x); 
		if(son[x]) Ed[x] = dfs2(son[x], x, Top); 
		for(int y : G[x]) if(y != fa && y != son[x]) { dfs2(y, x, y); }
		return Ed[x]; 
	}
	void dfs3(int x, int fa) {
		for(int y : G[x]) if(y != fa) { dfs3(y, x); }
		if(x == top[x]) {
			int qmx = Seg.quemx(1, 1, n, dfn[x], dfn[Ed[x]]).mx; 
			ans_set.insert(qmx); 
			auto qR = Seg.queRmx(1, 1, n, dfn[x], dfn[Ed[x]]); 
//			debug("%lld : [%lld %lld] %lld | %lld fa %lld\n", x, dfn[x], dfn[Ed[x]], qmx, qR.se, fa); 
			if(fa) { Seg.update(1, 1, n, dfn[fa], qR.se, 1); }
		}
	}
	void Main() {
		for(i=1; i<n; ++i) {
			u = read(); v = read(); 
			G[u].pb(v); G[v].pb(u); 
		}
		for(i=1; i<=n; ++i) a[i] = read(); 
		dfs(1, 0); dfs2(1, 0, 1); 
		Seg.build(1, 1, n, a); 
//		for(i = 1; i <= n; ++i) debug("%d ", dfn[i]); 
//		for(i = 1; i <= n; ++i) debug("%d ", top[i]); debug("\n"); 
//		for(i = 1; i <= n; ++i) debug("%d ", Ed[i]); debug("\n"); 
		dfs3(1, 0); 
	}
}

namespace Operation {
	void Update(int x, int y) {
		stack<int>z; 
		int k = x; x = top[x]; 
//		printf("# %lld\n", x); 
		while(1) { /*assert(x>=1 && x<=n); */
		z.push(x); if(!F[x]) break; x = F[x]; x = top[x]; }
		while(!z.empty()) { 
//			z.push(x); 
			x = z.top(); z.pop(); 
			int qmx = Seg.quemx(1, 1, n, dfn[x], dfn[Ed[x]]).mx; 
			ans_set.erase(ans_set.find(qmx)); 
//			debug("Erase : %lld (%lld %lld)\n", qmx, x, F[x]); 
			auto qR = Seg.queRmx(1, 1, n, dfn[x], dfn[Ed[x]]); 
			if(F[x]) { Seg.update(1, 1, n, dfn[F[x]], qR.se, -1); }
//			else break; 
//			x = F[x]; x = top[x]; 
		}
		x = k; 
		Seg.add(1, 1, n, dfn[x], y); 
		x = top[x]; 
//		while(!z.empty()) {
		while(1) {
//			x = z.top(); z.pop(); 
			int qmx = Seg.quemx(1, 1, n, dfn[x], dfn[Ed[x]]).mx; 
			ans_set.insert(qmx); 
			auto topmx = Seg.queRmx(1, 1, n, dfn[x], dfn[Ed[x]]); 
//			debug("Insert : %lld (%lld %lld) topmx %lld\n", qmx, x, F[x], topmx.se); 
			if(F[x]) { Seg.update(1, 1, n, dfn[F[x]], topmx.se, 1); }
			else break; 
			x = F[x]; x = top[x]; 
		}
	}
	int Qans() {
		auto t = ans_set.end(); --t; 
		return (*t); 
	}
	void Main() {
		int cnt = 0; 
		while(q--) {
			op = read(); 
//			printf("%d : ", op); 
//			if(q%100 == 0) 
//			printf("%lld : ", ++cnt); 
			if(q<=80769) debug("%d\n", q); 
			if(op == 1) {
				printf("%lld\n", Qans()); 
			}
			if(op == 2) {
				u = read(); 
				Update(u, 1e16); 
				int k = Qans(); 
//				debug("%lld\n", k); 
				printf("%lld\n", k - (int)1e16 + a[u]); 
				Update(u, a[u]); 
			}
			if(op == 3) {
				u = read(); v = read(); 
				Update(u, v); a[u] = v; 
			}
//			debug("----------------------\n"); 
		}
	}
}

signed main()
{
	freopen("taffy.in", "r", stdin);
	freopen("taffy.out", "w", stdout);
	#ifdef LOCAL
	  freopen("in.txt", "r", stdin);
	  freopen("out.txt", "w", stdout);
	#endif
//	srand(time(NULL));
//	T=read();
//	while(T--) {
//
//	}
	n = read(); q = read(); 
	Tree :: Main(); 
	Operation :: Main(); 
	return 0;
}

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值