zoukankan      html  css  js  c++  java
  • POJ 3237 Tree 树链剖分

    树链剖分基础题

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 10010;
    struct edge
    {
    	int v, next;
    }e[maxn*2];
    int first[maxn], cnt;
    
    int top[maxn], dep[maxn], sz[maxn], f[maxn], son[maxn], rank[maxn], tid[maxn];
    int tp, tim;
    int d[maxn][3];
    int n;
    void AddEdge(int u, int v)
    {
    	e[cnt].v = v;
    	e[cnt].next = first[u];
    	first[u] = cnt++;
    	
    	e[cnt].v = u;
    	e[cnt].next = first[v];
    	first[v] = cnt++;
    	
    }
    void init()
    {
    	memset(first, -1, sizeof(first));
    	cnt = 1;
    	memset(son, -1, sizeof(son));
    	tim = 0;
    }
    
    void dfs1(int u, int fa, int d)
    {
    	sz[u] = 1;
    	dep[u] = d;
    	f[u] = fa;	
    	for(int i = first[u]; i != -1; i = e[i].next)
    	{
    		int v = e[i].v;
    		if(v == fa)
    			continue;
    		dfs1(v, u, d+1);
    		sz[u] += sz[v];
    		if(son[u] == -1 || sz[son[u]] < sz[v])
    			son[u] = v;
    	}
    }
    
    void dfs2(int u, int tp)
    {
    	top[u] = tp;
    	tid[u] = ++tim;
    	rank[tid[u]] = u;
    	if(son[u] == -1)
    		return;
    	dfs2(son[u], tp);
    	for(int i = first[u]; i != -1; i = e[i].next)
    	{
    		int v = e[i].v;
    		if(v != f[u] && son[u] != v)
    			dfs2(v, v);
    	}
    }
    
    int ma[maxn<<2];
    int mi[maxn<<2];
    int lz[maxn<<2];
    void pushup(int l, int r, int rt)
    {
    	ma[rt] = max(ma[rt<<1], ma[rt<<1|1]);
    	mi[rt] = min(mi[rt<<1], mi[rt<<1|1]);
    }
    void build(int l, int r, int rt)
    {	
    	ma[rt] = 0;
    	mi[rt] = 0;
    	lz[rt] = 0;
    	if(l == r)
    	{
    		return;
    	}
    	int m = (l + r) >> 1;
    	build(l, m, rt<<1);
    	build(m+1, r, rt<<1|1);
    }
    void pushdown(int l, int r, int rt)
    {
    	if(l == r)
    		return;
    	if(lz[rt])
    	{
    		mi[rt<<1] = -mi[rt<<1];
    		ma[rt<<1] = -ma[rt<<1];
    		swap(mi[rt<<1], ma[rt<<1]);
    		mi[rt<<1|1] = -mi[rt<<1|1];
    		ma[rt<<1|1] = -ma[rt<<1|1];
    		swap(mi[rt<<1|1], ma[rt<<1|1]);	
    		lz[rt<<1] ^= 1;
    		lz[rt<<1|1] ^= 1;
    		lz[rt] = 0;
    	}
    }
    void update(int x, int y, int l, int r, int rt)
    {
    	if(x == l && y == r)
    	{
    		mi[rt] = -mi[rt];
    		ma[rt] = -ma[rt];
    		swap(mi[rt], ma[rt]);
    		lz[rt] ^= 1;
    		return;
    	}
    	pushdown(l, r, rt);
    	int m = (l + r) >> 1;
    	if(y <= m)
    		update(x, y, l, m, rt<<1);
    	else if(x > m)
    		update(x, y, m+1, r, rt<<1|1);
    	else
    	{
    		update(x, m, l, m, rt<<1);
    		update(m+1, y, m+1, r, rt<<1|1);
    	}
    	pushup(l, r, rt);
    }
    void update2(int x, int l, int r, int rt, int w)
    {
    	if(l == r)
    	{
    		ma[rt] = mi[rt] = w;
    		lz[rt] = 0;
    		return;
    	}
    	pushdown(l, r, rt);
    	int m = (l + r) >> 1;
    	if(x <= m)
    		update2(x, l, m, rt<<1, w);
    	else
    		update2(x, m+1, r, rt<<1|1, w);
    	pushup(l, r, rt);
    }
    int query(int x, int y, int l, int r, int rt)
    {
    	if(l == x && r == y)
    		return ma[rt];
    	pushdown(l, r, rt);
    	
    	int m = (l + r) >> 1;
    	if(y <= m)
    		return query(x, y, l, m, rt<<1);
    	else if(x > m)
    		return query(x, y, m+1, r, rt<<1|1);
    	else
    	{
    		return max(query(x, m, l, m, rt<<1), query(m+1, y, m+1, r, rt<<1|1));
    	}
    }
    
    void change(int u, int v)
    {
    	while(top[u] != top[v])
    	{
    		if(dep[top[u]] < dep[top[v]])
    			swap(u, v);
    		update(tid[top[u]], tid[u], 1, n, 1);
    		u = f[top[u]];
    	}
    	if(u == v)
    		return;
    	if(dep[u] > dep[v])
    		swap(u, v);
    	update(tid[son[u]], tid[v], 1, n, 1);
    }
    int find(int u, int v)
    {
    	int ans = -999999999;
    	while(top[u] != top[v])
    	{
    		if(dep[top[u]] < dep[top[v]])
    			swap(u, v);
    		ans = max(ans, query(tid[top[u]], tid[u], 1, n, 1));
    		u = f[top[u]];
    	}
    	if(u == v)
    		return ans;
    	if(dep[u] > dep[v])
    		swap(u, v);
    	ans = max(ans, query(tid[son[u]], tid[v], 1, n, 1));
    	return ans;
    }
    int main()
    {
    	int T;
    	scanf("%d", &T);
    	while(T--)
    	{
    		init();
    		
    		scanf("%d", &n);
    		for(int i = 1; i < n; i++)
    		{
    			int u, v, w;
    			scanf("%d %d %d", &u, &v, &w);
    			AddEdge(u, v);
    			d[i][0] = u;
    			d[i][1] = v;
    			d[i][2] = w;
    		}
    		dfs1(1, 0, 0);
    		dfs2(1, 1);
    		build(1, n, 1);
    		
    		for(int i = 1; i < n; i++)
    		{
    			if(dep[d[i][0]] > dep[d[i][1]])
    				swap(d[i][0], d[i][1]);
    			update2(tid[d[i][1]], 1, n, 1, d[i][2]);
    		}
    		char s[10];
    		while(scanf("%s", s) && strcmp(s, "DONE"))
    		{
    			if(s[0] == 'Q')
    			{
    				int x, y;
    				scanf("%d %d", &x, &y);
    				printf("%d
    ", find(x, y));
    			}
    			else if(s[0] == 'C')
    			{
    				int x, y;
    				scanf("%d %d", &x, &y);
    				update2(tid[d[x][1]], 1, n, 1, y);
    			}
    			else
    			{
    				int x, y;
    				scanf("%d %d", &x, &y);
    				change(x, y);
    			}
    		}
    	} 
    	return 0;
    }
    


  • 相关阅读:
    博客园
    未释放的已删除文件
    ssh连接缓慢
    剑指 Offer 38. 字符串的排列
    剑指 Offer 37. 序列化二叉树
    剑指 Offer 50. 第一个只出现一次的字符
    剑指 Offer 36. 二叉搜索树与双向链表
    剑指 Offer 35. 复杂链表的复制
    剑指 Offer 34. 二叉树中和为某一值的路径
    剑指 Offer 33. 二叉搜索树的后序遍历序列
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/7064387.html
Copyright © 2011-2022 走看看