zoukankan      html  css  js  c++  java
  • [洛谷P4315] 月下”毛景“树

    题目链接:##

    点我

    题目分析:##

    树剖。将边权下放到下方点上(为什么要选深度更深的点?一个父亲可能对应多个儿子,但一个儿子只有一个父亲,即可以保证每个点只保存一条边权)成为经典点权+树剖裸题
    注意链计算时不能把LCA算进去,其余细节较多,具体见代码。

    代码:##

    #include<bits/stdc++.h>
    #define N (100000 + 5)
    #define inf (1000000000+7)
    using namespace std;
    inline int read() {
    	int cnt = 0, f = 1; char c;
    	c = getchar();
    	while(!isdigit(c)) {
    		if (c == '-') f = -f;
    		c = getchar(); 
    	}
    	while(isdigit(c)) {
    		cnt = cnt * 10 + c - '0';
    		c = getchar();
    	}
    	return cnt * f;
    }
    int nxt[N * 2], first[N * 2], to[N * 2], w[N * 2], a[N], tot;
    int father[N], top[N], siz[N], dep[N], son[N], num[N], id[N], idx;
    int n, u, v, W, k;
    char opr[20];
    struct node{
    	int l, r;
    	long long cov, add, gmax;
    	#define l(p) tree[p].l
    	#define r(p) tree[p].r
    	#define cov(p) tree[p].cov
    	#define add(p) tree[p].add
    	#define gmax(p) tree[p].gmax
    } tree[N * 4];
    
    struct edge{
    	int u; int v;
    }e[N * 2];
    
    void Add(int x, int y, int z) {
    	nxt[++tot] = first[x];
    	first[x] = tot;
    	to[tot] = y;
    	w[tot] = z;
    }
    
    void dfs1(int cur, int fa) {
    	father[cur] = fa; siz[cur] = 1; dep[cur] = dep[fa] + 1;
    	for (register int i = first[cur]; i; i = nxt[i]) {
    		int v = to[i];
    		if(v != fa) {
    			a[v] = w[i];
    			dfs1(v, cur);
    			siz[cur] += siz[v];
    			if(siz[son[cur]] < siz[v]) son[cur] = v;
    		}
    	}
    }
    
    void dfs2(int cur, int tp) {
    	top[cur] = tp; num[cur] = ++idx; id[idx] = cur;
    	if (son[cur]) dfs2(son[cur], tp);
    	for (register int i = first[cur]; i; i = nxt[i]) {
    		int v = to[i];
    		if (!num[v]) dfs2(v, v);
    	}
    }
    
    void pushup(int p) {
    	gmax(p) = max(gmax(p << 1), gmax(p << 1 | 1));
    }
    void pushcover(int p, int v){cov(p) = v; add(p) = 0; gmax(p) = v;}
    void pushadd(int p,int v){ add(p)+=v; gmax(p)+=v;}
    void pushdown(int p) {
    	if (cov(p) >= 0) {
    		pushcover(p<<1, cov(p)); pushcover(p<<1|1, cov(p)); cov(p) = -1; 
    	}
    	if (add(p)) {
    		pushadd(p<<1, add(p)); pushadd(p<<1|1, add(p)); add(p) = 0; 
    	}
    }
    
    void build_tree(int p, int l, int r) {
    	l(p) = l; r(p) = r;	cov(p) = -1;
    	if(l == r) {
    		gmax(p) = a[id[l]];
    	//	cout<<l<<" "<<r<<" "<<gmax(p)<<endl;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	build_tree(p << 1, l, mid);
    	build_tree(p << 1 | 1, mid + 1, r);
    	pushup(p);
    }
    void debug(int u,int l,int r){
    	if(l==r){
    		cout<<id[l]<<" "<<gmax(u)<<endl;return;
    	}int mid=(l+r)>>1;
    	debug(u*2,l,mid);debug(u*2+1,mid+1,r);
    }
    void Cover(int p, int l, int r, int d) {
    	if (l > r) return;
    	if (l <= l(p) && r >= r(p)) {
    		pushcover(p, d);
    		return;
    	}
    	pushdown(p);
    	int mid = (l(p) + r(p)) >> 1;
    	if (l <= mid) Cover(p << 1, l, r, d);
    	if (r > mid) Cover(p << 1 | 1, l, r, d);
    	pushup(p);
    }
    
    void Modify(int p, int l, int r, int d) {
    	if (l > r) return;
    	if (l <= l(p) && r >= r(p)) {
    //		if(cov(p) >= 0) {
    //			cov(p) += d;
    //			gmax(p) += d;
    //		} else {
    //			pushadd(p, d);
    //		}
    		pushadd(p, d);
    		return;
    	}
    	pushdown(p);
    	int mid = (l(p) + r(p)) >> 1; 
    	if (l <= mid) Modify(p << 1, l, r, d);
    	if (r > mid) Modify(p << 1 | 1, l, r, d);
    	pushup(p);
    }
    
    long long query(int p, int l, int r) {
    //	cout<<p<<" "<<l(p)<<" "<<r(p)<<endl; 
    	if (l <= l(p) && r >= r(p)) return gmax(p);
    	int mid = (l(p) + r(p)) >> 1;
    	pushdown(p);
    	//cout<<p<<endl;
    	long long val = -inf;
    	if (l <= mid) val = max (val, query(p << 1, l, r));
    	if (r > mid) val = max(val, query(p << 1 | 1, l, r));
    	return val;
    }
    
    void chain_cover(int u, int v, int d) {
    	while (top[u] != top[v]) {
    		if (dep[top[u]] < dep[top[v]]) swap(u, v);
    		Cover(1, num[top[u]], num[u], d);
    		u = father[top[u]];
    	}
    	if (dep[u] < dep[v]) swap(u, v);
    //	if (u == v) Cover(1, num[v], num[u], d);
    	Cover(1, num[v] + 1, num[u], d);
    }
    
    void chain_modify(int u, int v, int d) {
    	while (top[u] != top[v]) {
    		if (dep[top[u]] < dep[top[v]]) swap(u, v);
    		Modify(1, num[top[u]], num[u], d);
    		u = father[top[u]];
    	}
    	if (dep[u] < dep[v]) swap(u, v);
    //	if (u == v) Modify(1, num[v], num[u], d);
    	Modify(1, num[v] + 1, num[u], d);
    }
    
    long long chain_query(int u, int v) { 
    	long long ans = -inf;
    	while (top[u] != top[v]) {//cout<<u<<endl;
    	//	cout<<top[u]<<" "<<top[v]<<endl;
    		if (dep[top[u]] < dep[top[v]]) swap(u, v);
    	//	cout<<top[u]<<" "<<top[v]<<endl;
    	//	cout<<num[top[u]]<<" "<<num[u]<<endl;
    	//	cout<<query(1,num[top[u]],num[u])<<"###"<<endl;
    		ans = max(ans, query(1, num[top[u]], num[u]));//cout<<"#";
    		u = father[top[u]];
    	//	cout<<ans<<endl;
    	}
    	if (dep[u] < dep[v]) swap(u, v);
    	ans = max(ans, query(1, num[v] + 1, num[u]));
    	return ans;
    }
    
    void solve() {
    	n = read();
    	for (register int i = 1; i < n; i++) {
    		u = read(); v = read(); W = read();
    		e[i].u = u; e[i].v = v;
    		Add(u, v, W); Add(v, u, W);
    	}
    	dfs1(1, 0); dfs2(1, 1);
    //	for(int i=1;i<=n;i++)cout<<a[i]<<" ";cout<<endl;
    //	for(int i=1;i<=n;i++)cout<<id[i]<<" ";cout<<endl;
    	build_tree(1, 1, n);
    //	debug(1,1,n);
    //	cout<<"#"<<endl;
    	for (;;) {
    		scanf("%s", opr + 1);
    		if (opr[1] == 'M') {
    			u = read(); v = read(); 
    			printf("%lld
    ", chain_query(u, v));
    		}
    		if (opr[1] == 'C') {
    			if (opr[2] == 'o') {
    				u = read(); v = read(); W = read();
    				chain_cover(u, v, W);
    			}
    			if (opr[2] == 'h') {
    				u = read(); W = read();
    				if (dep[e[u].u] < dep[e[u].v]) swap(e[u].u, e[u].v);
    //				cout<<"nmsl"<<e[u].u<<" "<<e[u].v<<endl;
    //				cout<<"##"<<num[e[u].u]<<"WWW"<<W<<endl;
    //				chain_cover(num[e[u].u], num[e[u].v], W);
    				Cover(1, num[e[u].u], num[e[u].u], W);
    			}
    		}
    		if (opr[1] == 'A') {
    			u = read(); v = read(); W = read();
    			chain_modify(u, v, W);
    		}
    		if (opr[1] == 'S') break;
    //		debug(1,1,n);cout<<endl;
    	}
    	return;
    }
    
    int main() {
    //	freopen("input.in","r",stdin);
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    第12讲:数据库完整性
    第11讲:视图及其应用
    第10讲:利用SQL语言实现关系代数操作
    ArcEngine 坐标系转换
    [转]ArcGIS计算图斑的四邻坐标(XMin,XMax,YMin,YMax)
    oracle11g 修改字符集 修改为ZHS16GBK
    Oracle 全文索引相关命令
    SQL语句 递归
    流量操控之SSH隧道与端口转发
    VIM 常用操作
  • 原文地址:https://www.cnblogs.com/kma093/p/11059141.html
Copyright © 2011-2022 走看看