zoukankan      html  css  js  c++  java
  • 洛谷 P2486 [SDOI2011]染色(树链剖分+线段树)

    题目链接

    题解

    比较裸的树链剖分 好像树链剖分的题都很裸

    线段树中维护一个区间最左和最右的颜色,和答案
    合并判断一下中间一段就可以了

    比较考验代码能力

    Code

    #include<bits/stdc++.h>
    #define LL long long
    #define RG register
    using namespace std;
    
    inline int gi() {
        int f = 1, s = 0;
        char c = getchar();
        while (c != '-' && (c < '0' || c > '9')) c = getchar();
        if (c == '-') f = -1, c = getchar();
        while (c >= '0' && c <= '9') s = s*10+c-'0', c = getchar();
        return f == 1 ? s : -s;
    }
    const int N = 100010;
    struct node {
    	int to, next;
    }g[N<<1];
    int last[N], gl;
    inline void add(int x, int y) {
    	g[++gl] = (node) {y, last[x]};
    	last[x] = gl;
    	g[++gl] = (node) {x, last[y]};
    	last[y] = gl;
    	return ;
    }
    
    int c[N];
    
    struct Segment_tree {
    	int l, r, v, lazy;
    }t[N<<2];
    
    int fa[N], siz[N], son[N], cnt, s[N], top[N], id[N], dep[N];
    void dfs1(int u, int f) {
    	siz[u] = 1; fa[u] = f;
    	int MAX = 0;
    	for (int i = last[u]; i; i = g[i].next) {
    		int v = g[i].to;
    		if (v == f) continue;
    		dep[v] = dep[u]+1;
    		dfs1(v, u);
    		siz[u] += siz[v];
    		if (MAX < siz[v]) MAX = siz[v], son[u] = v;
    	}
    	return ;
    }
    
    void dfs2(int u, int topf) {
    	top[u] = topf;
    	s[++cnt] = c[u];
    	id[u] = cnt;
    	if (!son[u]) return ;
    	dfs2(son[u], topf);
    	for (int i = last[u]; i; i = g[i].next) {
    		int v = g[i].to;
    		if (v == fa[u] || v == son[u]) continue;
    			dfs2(v, v);
    	}
    	return ;
    }
    #define mid ((l+r)>>1)
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    
    
    void pushup(int rt) {	
    	t[rt].l = t[ls].l; t[rt].r = t[rs].r;
    	t[rt].v = t[ls].v + t[rs].v;
    	if (t[ls].r == t[rs].l) t[rt].v--;
    	return ;
    }
    
    void build(int rt, int l, int r) {
    	if (l == r) {
    		t[rt] = (Segment_tree) {s[l], s[l], 1, 0};
    		return ;
    	}
    	build(ls, l, mid); build(rs, mid+1, r);
    	pushup(rt);
    	return ;
    }
    void pushdown(int rt) {
    	int lazy = t[rt].lazy;
    	t[rt].lazy = 0;
    	if (lazy) {
    		t[rs].lazy = t[ls].lazy = lazy;
    		t[rs].l = t[rs].r = t[ls].l = t[ls].r = lazy;
    		t[rs].v = t[ls].v = 1;
    	}
    	return ;
    }
    void update(int rt, int l, int r, int L, int R, int k) {
    	if (L <= l && r <= R) {
    		t[rt].v = 1;
    		t[rt].lazy = t[rt].l = t[rt].r = k;
    		return ;
    	}
    	pushdown(rt);
    	if (L <= mid) update(ls, l, mid, L, R, k);
    	if (R > mid) update(rs, mid+1, r, L, R, k);
    	pushup(rt);
    	return ;
    }
    
    struct zzy {
    	int l, r, v;
    }; 
    
    zzy merge(zzy a, zzy b) {
    	if (!a.v) return b;
    	if (!b.v) return a;
    	return (zzy) {a.l, b.r, a.v+b.v-(a.r == b.l)};
    }
    
    zzy query(int rt, int l, int r, int L, int R) {
    	if (L <= l && r <= R)
    		return (zzy) {t[rt].l, t[rt].r, t[rt].v};
    	zzy z = (zzy) {0, 0, 0};
    	pushdown(rt);
    	if (L <= mid)
    		z = query(ls, l, mid, L, R);
    	if (R > mid)
    		z = merge(z, query(rs, mid+1, r, L, R));
    	return z;
    }
    
    void upway(int x, int y, int z) {
    	while (top[x] != top[y]) {
    		if (dep[top[x]] < dep[top[y]]) swap(x, y);
    		update(1, 1, cnt, id[top[x]], id[x], z);
    		x = fa[top[x]];
    	}
    	if (dep[x] > dep[y]) swap(x, y);
    	update(1, 1, cnt, id[x], id[y], z);
    	return ;
    }
    
    int qway(int x, int y) {
    	zzy zx, zy;
    	zx = zy = (zzy) {0, 0, 0};
    	while (top[x] != top[y]) {
    		if (dep[top[x]] >= dep[top[y]]) {
    			zx = merge(query(1, 1, cnt, id[top[x]], id[x]), zx);
    			x = fa[top[x]];
    		}
    		else {
    			zy = merge(query(1, 1, cnt, id[top[y]], id[y]), zy);
    			y = fa[top[y]];
    		}
    	}
    	if (dep[x] > dep[y]) swap(x, y), swap(zx, zy);
    	zy = merge(query(1, 1, cnt, id[x], id[y]), zy);
    	zx.v += zy.v;
    	if (zx.l == zy.l) zx.v--;
    	return zx.v;
    }
    
    int main() {
    	int n = gi(), m = gi();
    	for (int i = 1; i <= n; i++) c[i] = gi();
    	for (int i = 1; i < n; i++) add(gi(), gi());
    	dfs1(1, 0);
    	dfs2(1, 1);
    	build(1, 1, n);
    	while (m--) {
    		char c; cin>>c;
    		if (c == 'C') {
    			int x = gi(), y = gi(), z = gi();
    			upway(x, y, z);
    		}
    		else {
    			int x = gi(), y = gi();
    			printf("%d
    ", qway(x, y));
    		}
    	}
        return 0;
    }
    
  • 相关阅读:
    缓存
    java内存模型—先行发生原则
    Java中的阻塞队列
    java的Map
    事务传播性、隔离性与MVCC
    final修饰符
    领域驱动设计和实践
    对象转换利器之Dozer
    SharePoint Iframe 报错“此内容不能显示在一个框架中”
    使用SVG symbols建立图标系统
  • 原文地址:https://www.cnblogs.com/zzy2005/p/9868064.html
Copyright © 2011-2022 走看看