• HDU 5002 Tree


    题意:

    一棵树  支持删边加边、路径权值加值、路径权值改值、路径求第二大的数字和其个数

    思路:

    LCT的第二题  题意已经把功能都告诉了  比較裸

    要注意的是权值加值和改值两个操作的标记下放问题  要先down改值  再down加值

    对于路径的操作通过mroot变换树的形态再access拿出路径比較方便  不要像我上一篇一样搞lca

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<map>
    #include<set>
    #include<vector>
    #include<queue>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    using namespace std;
    #define N 100010
    #define L(x) (ch[x][0])
    #define R(x) (ch[x][1])
    #define inf -2147483640
    
    int ch[N][2], pre[N], rev[N], me[N];
    int cov[N], add[N], size[N], max1[N], num1[N], max2[N], num2[N];
    bool rt[N];
    
    struct helper {
    	int val, num;
    	bool operator<(const helper ff) const {
    		return val > ff.val;
    	}
    } hel[10];
    
    void Update_COV(int u, int d) {
    	if (!u)
    		return;
    	me[u] = d;
    	cov[u] = d;
    	add[u] = inf;
    	max1[u] = d;
    	num1[u] = size[u];
    	max2[u] = inf;
    	num2[u] = 0;
    }
    
    void Update_Add(int u, int d) {
    	if (!u)
    		return;
    	me[u] += d;
    	if (add[u] != inf)
    		add[u] += d;
    	else
    		add[u] = d;
    	max1[u] += d;
    	if (max2[u] != inf)
    		max2[u] += d;
    }
    
    void Update_Rev(int u) {
    	if (!u)
    		return;
    	swap(L(u), R(u));
    	rev[u] ^= 1;
    }
    
    void down(int u) {
    	if (rev[u]) {
    		Update_Rev(L(u));
    		Update_Rev(R(u));
    		rev[u] = 0;
    	}
    	if (cov[u] != inf) {
    		Update_COV(L(u), cov[u]);
    		Update_COV(R(u), cov[u]);
    		cov[u] = inf;
    	}
    	if (add[u] != inf) {
    		Update_Add(L(u), add[u]);
    		Update_Add(R(u), add[u]);
    		add[u] = inf;
    	}
    }
    
    void up(int u) {
    	size[u] = size[L(u)] + size[R(u)] + 1;
    	hel[0].val = max1[L(u)];
    	hel[0].num = num1[L(u)];
    	hel[1].val = max2[L(u)];
    	hel[1].num = num2[L(u)];
    	hel[2].val = max1[R(u)];
    	hel[2].num = num1[R(u)];
    	hel[3].val = max2[R(u)];
    	hel[3].num = num2[R(u)];
    	hel[4].val = me[u];
    	hel[4].num = 1;
    	sort(hel, hel + 5);
    	int i;
    	for (i = 1; i < 5; i++) {
    		if (hel[i].val != hel[i - 1].val)
    			break;
    	}
    	max1[u] = hel[0].val;
    	max2[u] = hel[i].val;
    	num1[u] = num2[u] = 0;
    	for (i = 0; i < 5; i++) {
    		if (hel[i].val == max1[u])
    			num1[u] += hel[i].num;
    		else if (hel[i].val == max2[u])
    			num2[u] += hel[i].num;
    	}
    }
    
    //Rotate P Splay 一般不变
    void Rotate(int x) {
    	int y = pre[x], kind = ch[y][1] == x;
    	ch[y][kind] = ch[x][!kind];
    	pre[ch[y][kind]] = y;
    	pre[x] = pre[y];
    	pre[y] = x;
    	ch[x][!kind] = y;
    	if (rt[y])
    		rt[y] = false, rt[x] = true;
    	else
    		ch[pre[x]][ch[pre[x]][1] == y] = x;
    	up(y);
    }
    
    //P函数先将splay根结点到u的路径上全部的结点的标记逐级下放
    void P(int u) {
    	if (!rt[u])
    		P(pre[u]);
    	down(u);
    }
    
    void Splay(int u) {
    	P(u);
    	while (!rt[u]) {
    		int fa = pre[u], ffa = pre[fa];
    		if (rt[fa])
    			Rotate(u);
    		else if ((R(ffa) == fa) == (R(fa) == u))
    			Rotate(fa), Rotate(u);
    		else
    			Rotate(u), Rotate(u);
    	}
    	up(u);
    }
    
    //将root到u的路径变成实边
    int Access(int u) {
    	int v = 0;
    	for (; u; u = pre[v = u]) {
    		Splay(u);
    		rt[R(u)] = true, rt[R(u) = v] = false;
    		up(u);
    	}
    	return v;
    }
    
    //使u成为它所在的树的根
    void mroot(int u) {
    	Access(u);
    	Splay(u);
    	Update_Rev(u);
    }
    
    //连接两棵树  u接在v上
    void link(int u, int v) {
    	mroot(u);
    	pre[u] = v;
    }
    
    //u-v边断开
    void cut(int u, int v) {
    	mroot(u);
    	Access(u);
    	Splay(v);
    	pre[L(v)] = pre[v];
    	pre[v] = 0;
    	rt[L(v)] = true;
    	L(v) = 0;
    	up(v);
    }
    
    //u-v路径权值变为w
    void COV(int u, int v, int w) {
    	mroot(u);
    	Access(v);
    	Splay(v);
    	Update_COV(v, w);
    }
    
    //u-v路径+w
    void ADD(int u, int v, int w) {
    	mroot(u);
    	Access(v);
    	Splay(v);
    	Update_Add(v, w);
    }
    
    //u-v路径最大值
    void query(int u, int v) {
    	mroot(u);
    	Access(v);
    	Splay(v);
    	if (max2[v] != inf)
    		printf("%d %d
    ", max2[v], num2[v]);
    	else
    		printf("ALL SAME
    ");
    }
    
    struct edge {
    	int v, next;
    } ed[N * 2];
    int head[N], tot;
    
    void addedge(int u, int v) {
    	ed[tot].v = v;
    	ed[tot].next = head[u];
    	head[u] = tot++;
    }
    
    //利用dfs初始化pre数组  建立LCT
    void dfs(int u) {
    	for (int i = head[u]; ~i; i = ed[i].next) {
    		int v = ed[i].v;
    		if (pre[v] != 0)
    			continue;
    		pre[v] = u;
    		dfs(v);
    	}
    }
    
    int main() {
    	int T, t, n, m, i, op, u, v, x, y, w;
    	max1[0] = max2[0] = inf;
    	rt[0] = true;
    	scanf("%d", &T);
    	for (t = 1; t <= T; t++) {
    		scanf("%d%d", &n, &m);
    		for (i = 1; i <= n; i++) {
    			scanf("%d", &me[i]);
    			max1[i] = me[i];
    			max2[i] = inf;
    			num1[i] = 1;
    			num2[i] = 0;
    			size[i] = 1;
    			add[i] = cov[i] = inf;
    			L(i) = R(i) = pre[i] = rev[i] = 0;
    			rt[i] = true;
    		}
    		tot = 0;
    		memset(head, -1, sizeof(head));
    		for (i = 1; i < n; i++) {
    			scanf("%d%d", &u, &v);
    			addedge(u, v);
    			addedge(v, u);
    		}
    		pre[1] = -1;
    		dfs(1);
    		pre[1] = 0;
    		printf("Case #%d:
    ", t);
    		while (m--) {
    			scanf("%d", &op);
    			if (op == 1) {
    				scanf("%d%d%d%d", &u, &v, &x, &y);
    				cut(u, v);
    				link(x, y);
    			} else if (op == 2) {
    				scanf("%d%d%d", &u, &v, &w);
    				COV(u, v, w);
    			} else if (op == 3) {
    				scanf("%d%d%d", &u, &v, &w);
    				ADD(u, v, w);
    			} else {
    				scanf("%d%d", &u, &v);
    				query(u, v);
    			}
    		}
    	}
    	return 0;
    }
    


  • 相关阅读:
    Linux下Mysql的odbc配置
    Android:ScaleType设置图片
    Android:@id和@+id
    Android:控件布局(线性布局)LinearLayout
    Android:控件的对象修改控件的值
    Android:为控件绑定监听器
    Android四大基本组件
    java:I/O 根据用户输入反馈信息
    java:I/O 往原文件追加内容
    java:I/O 一行一行读取和写入
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5098387.html
Copyright © 2020-2023  润新知