• P4315 月下“毛景树”


    P4315 月下“毛景树”

    题目描述
    毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。

    爬啊爬~爬啊爬毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:

    Change k w:将第k条树枝上毛毛果的个数改变为w个。

    Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。

    Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:

    Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

    Solution

    树剖
    注意线段树下推标记时分清楚对子节点标记的影响

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    #define REP(i, x, y) for(int i = (x);i <= (y);i++)
    using namespace std;
    int RD(){
        int out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const int maxn = 100019,INF = 1e9 + 19;
    int head[maxn],nume = 1;
    struct Node{
        int v,dis,nxt;
        }E[maxn << 3];
    void add(int u,int v,int dis){
        E[++nume].nxt = head[u];
        E[nume].v = v;
        E[nume].dis = dis;
        head[u] = nume;
        }
    int num;
    int size[maxn], wson[maxn], dep[maxn], fa[maxn], val[maxn];
    int top[maxn], pos[maxn], ori[maxn], tot;
    void dfs1(int u, int F){
    	size[u] = 1;
    	for(int i = head[u];i;i = E[i].nxt){
    		int v = E[i].v;
    		if(v == F)continue;
    		val[v] = E[i].dis;
    		dep[v] = dep[u] + 1;
    		fa[v] = u;
    		dfs1(v, u);
    		size[u] += size[v];
    		if(size[v] > size[wson[u]])wson[u] = v;
    		}
    	}
    void dfs2(int u, int TP){
    	top[u] = TP;
    	pos[u] = ++tot;
    	ori[tot] = u;
    	if(!wson[u])return ;
    	dfs2(wson[u], TP);
    	for(int i = head[u];i;i = E[i].nxt){
    		int v = E[i].v;
    		if(v == fa[u] || v == wson[u])continue;
    		dfs2(v, v);
    		}
    	}
    #define lid (id << 1)
    #define rid (id << 1) | 1
    struct seg_tree{
    	int l, r;
    	int max;
    	int add, set;
    	}tree[maxn << 2];
    void pushup(int id){tree[id].max = max(tree[lid].max, tree[rid].max);}
    void build(int id, int l, int r){
    	tree[id].l = l, tree[id].r = r, tree[id].set = -1;
    	if(l == r){
    		tree[id].max = val[ori[l]];
    		return ;
    		}
    	int mid = (l + r) >> 1;
    	build(lid, l, mid), build(rid, mid + 1, r);
    	pushup(id);
    	}
    void pushdown(int id){
    	if(tree[id].set != -1){
    		int v = tree[id].set;
    		tree[lid].max = tree[rid].max = v;
    		tree[lid].set = tree[rid].set = v;
    		tree[lid].add = tree[rid].add = 0;
    		tree[id].add = 0;
    		tree[id].set = -1;
    		}
    	if(tree[id].add != 0){
    		int v = tree[id].add;
    		tree[lid].max += v;
    		tree[rid].max += v;
    		if(tree[lid].set != -1)tree[lid].set += v;
    		if(tree[rid].set != -1)tree[rid].set += v;
    		tree[lid].add += v;
    		tree[rid].add += v;
    		tree[id].add = 0;
    		}
    	}
    void update(int id, int v, int l, int r, int o){
    	pushdown(id);
    	if(tree[id].l == l && tree[id].r == r){
    		if(o == 1){//1为全改变
    			tree[id].max = v;
    			tree[id].set = v;
    			}
    		else{//0为区间加
    			tree[id].max += v;
    			tree[id].add += v;
    			}
    		return ;
    		}
    	int mid = (tree[id].l + tree[id].r) >> 1;
    	if(mid < l)update(rid, v, l, r, o);
    	else if(mid >= r)update(lid, v, l, r, o);
    	else update(lid, v, l, mid, o), update(rid, v, mid + 1, r, o);
    	pushup(id);
    	}
    int query(int id, int l, int r){
    	pushdown(id);
    	if(tree[id].l == l && tree[id].r == r)return tree[id].max;
    	int mid = (tree[id].l + tree[id].r) >> 1;
    	if(mid < l)return query(rid, l, r);
    	else if(mid >= r)return query(lid, l, r);
    	else return max(query(lid, l, mid), query(rid, mid + 1, r));
    	}
    void uprange(int x, int y, int v, int o){
    	while(top[x] != top[y]){
    		if(dep[top[x]] < dep[top[y]])swap(x, y);
    		update(1, v, pos[top[x]], pos[x], o);
    		x = fa[top[x]];
    		}
    	if(x == y)return ;
    	if(dep[x] > dep[y])swap(x, y);
    	update(1, v, pos[x] + 1, pos[y], o);
    	}
    int Q_max(int x, int y){
    	int ret = 0;
    	while(top[x] != top[y]){
    		if(dep[top[x]] < dep[top[y]])swap(x, y);
    		ret = max(ret, query(1, pos[top[x]], pos[x]));
    		x = fa[top[x]];
    		}
    	if(x == y)return ret;
    	if(dep[x] > dep[y])swap(x, y);
    	ret = max(ret, query(1, pos[x] + 1, pos[y]));
    	return ret;
    	}
    struct EDG{int x, y;}I[maxn];
    void init(){
    	num = RD();
    	REP(i, 1, num - 1){
    		int u = RD(), v = RD(), dis = RD();
    		I[i] = (EDG){u, v};
    		add(u, v, dis), add(v, u, dis);
    		}
    	dep[1] = 1;
    	dfs1(1, -1);
    	dfs2(1, 1);
    	build(1, 1, num);
    	}
    void solve(){
    	char cmd[19];
    	while(1){
    		scanf("%s", cmd);
    		if(cmd[0] == 'S')return ;
    		else if(cmd[0] == 'C' && cmd[1] == 'h'){
    			int k = RD(), w = RD();
    			uprange(I[k].x, I[k].y, w, 1);
    			}
    		else if(cmd[0] == 'C' && cmd[1] == 'o'){
    			int x = RD(), y = RD(), w = RD();
    			uprange(x, y, w, 1);
    			}
    		else if(cmd[0] == 'A'){
    			int x = RD(), y = RD(), w = RD();
    			uprange(x, y, w, 0);
    			}
    		else{
    			int x = RD(), y = RD();
    			printf("%d
    ", Q_max(x, y));
    			}
    		}
    	}
    int main(){
    	init();
    	solve();
    	return 0;
    	}
    
  • 相关阅读:
    热烈祝贺自己的博客进入前1000名
    烈日之后逛成都
    懂得爱情
    腾飞天涯
    哈佛教授教你成为No.1的秘诀
    烈日炎炎
    有缘无份——因为伤感所以美丽
    时间管理
    亲爱的陌生人(转)
    走好激励第一步
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9895580.html
Copyright © 2020-2023  润新知