zoukankan      html  css  js  c++  java
  • _bzoj2243 [SDOI2011]染色【树链剖分】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2243

    裸的树链剖分,最开始我保存一个线段树节点的color值时(若有多种颜色则为-1),不小心使“若其两个子节点color相等,则该节点color值为其儿子的color,并把这个节点内颜色个数设为1”,这是致命的错误——万一两个儿子color都为-1呢?

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    
    const int maxn = 100005, maxm = 100005;
    
    int n, m, ini_c[maxn], t1, t2, t3, root;
    int head[maxn], to[maxn << 1], next[maxn << 1], lb;
    int fa[maxn], heavy[maxn], top[maxn], siz[maxn], dep[maxn], id[maxn], a[maxn], cnt;
    char opr;
    struct Node {
    	int ql, qr, c, num, lc, rc;
    } tree[maxn << 2];
    
    inline void ist(int aa, int ss) {
    	to[lb] = ss;
    	next[lb] = head[aa];
    	head[aa] = lb;
    	++lb;
    }
    void dfs1(int r, int dp) {
    	dep[r] = dp;
    	siz[r] = 1;
    	if (r == 6671) {
    		++r;
    		--r;
    	}
    	for (int j = head[r]; j != -1; j = next[j]) {
    		if (to[j] != fa[r]) {
    			fa[to[j]] = r;
    			dfs1(to[j], dp + 1);
    			siz[r] += siz[to[j]];
    			if (siz[to[j]] > siz[heavy[r]]) {
    				heavy[r] = to[j];
    			}
    		}
    	}
    }
    void dfs2(int r, int tp) {
    	if (!r) {
    		return;
    	}
    	id[r] = ++cnt;
    	a[cnt] = ini_c[r];
    	top[r] = tp;
    	dfs2(heavy[r], tp);
    	for (int j = head[r]; j != -1; j = next[j]) {
    		if (to[j] != fa[r] && to[j] != heavy[r]) {
    			dfs2(to[j], to[j]);
    		}
    	}
    }
    void make_tree(int p, int left, int right) {
    	tree[p].ql = left;
    	tree[p].qr = right;
    	if (left == right) {
    		tree[p].c = tree[p].lc = tree[p].rc = a[left];
    		tree[p].num = 1;
    		return;
    	}
    	int mid = (left + right) >> 1;
    	make_tree(p << 1, left, mid);
    	make_tree(p << 1 | 1, mid + 1, right);
    	if (tree[p << 1].c == tree[p << 1 | 1].c && tree[p << 1].c != -1) {
    		tree[p].c = tree[p].lc = tree[p].rc = tree[p << 1].c;
    		tree[p].num = 1;
    	}
    	else {
    		tree[p].c = -1;
    		tree[p].lc = tree[p << 1].lc;
    		tree[p].rc = tree[p << 1 | 1].rc;
    		tree[p].num = tree[p << 1].num + tree[p << 1 | 1].num;
    		if (tree[p << 1].rc == tree[p << 1 | 1].lc) {
    			--tree[p].num;
    		}
    	}
    }
    void upd(int p, int left, int right, int c) {
    	if (tree[p].ql == left && tree[p].qr == right) {
    		tree[p].c = tree[p].lc = tree[p].rc = c;
    		tree[p].num = 1;
    		return;
    	}
    	if (tree[p].c >= 0) {
    		if (tree[p].c == c) {
    			return;
    		}
    		tree[p << 1].c = tree[p << 1 | 1].c = tree[p].c;
    		tree[p << 1].lc = tree[p << 1].rc = tree[p].c;
    		tree[p << 1 | 1].lc = tree[p << 1 | 1].rc = tree[p].c;
    		tree[p << 1].num = tree[p << 1 | 1].num = 1;
    		tree[p].c = -1;
    	}
    	int mid = (tree[p].ql + tree[p].qr) >> 1;
    	if (right <= mid) {
    		upd(p << 1, left, right, c);
    	}
    	else if (left > mid) {
    		upd(p << 1 | 1, left, right, c);
    	}
    	else {
    		upd(p << 1, left, mid, c);
    		upd(p << 1 | 1, mid + 1, right, c);
    	}
    	tree[p].c = -1;
    	tree[p].lc = tree[p << 1].lc;
    	tree[p].rc = tree[p << 1 | 1].rc;
    	tree[p].num = tree[p << 1].num + tree[p << 1 | 1].num;
    	if (tree[p << 1].rc == tree[p << 1 | 1].lc) {
    		--tree[p].num;
    	}
    }
    int qry(int p, int left, int right, int & lc, int & rc) {
    	if (tree[p].ql == left && tree[p].qr == right) {
    		lc = tree[p].lc;
    		rc = tree[p].rc;
    		return tree[p].num;
    	}
    	if (tree[p].c >= 0) {
    		lc = rc = tree[p].c;
    		return 1;
    	}
    	int mid = (tree[p].ql + tree[p].qr) >> 1;
    	if (right <= mid) {
    		return qry(p << 1, left, right, lc, rc);
    	}
    	else if (left > mid) {
    		return qry(p << 1 | 1, left, right, lc, rc);
    	}
    	else {
    		int tlc, trc, rt1, rt2;
    		rt1 = qry(p << 1, left, mid, lc, trc);
    		rt2 = qry(p << 1 | 1, mid + 1, right, tlc, rc);
    		return rt1 + rt2 - (trc == tlc? 1: 0);
    	}
    }
    inline void C(int u, int v, int c) {
    	while (top[u] != top[v]) {
    		if (dep[top[u]] < dep[top[v]]) {
    			std::swap(u, v);
    		}
    		upd(1, id[top[u]], id[u], c);
    		u = fa[top[u]];
    	}
    	if (dep[u] < dep[v]) {
    		std::swap(u, v);
    	}
    	upd(1, id[v], id[u], c);
    }
    inline int Q(int u, int v) {
    	int rt = 0;
    	int u_lc1 = -666, u_rc1 = -666, u_lc2 = -666, u_rc2 = -666;
    	int v_lc1 = -666, v_rc1 = -666, v_lc2 = -666, v_rc2 = -666;
    	while (top[u] != top[v]) {
    		if (dep[top[u]] > dep[top[v]]) {
    			rt += qry(1, id[top[u]], id[u], u_lc2, u_rc2);
    			if (u_rc2 == u_lc1) {
    				--rt;
    			}
    			u_lc1 = u_lc2;
    			u_rc1 = u_rc2;
    			u = fa[top[u]];
    		}
    		else {
    			rt += qry(1, id[top[v]], id[v], v_lc2, v_rc2);
    			if (v_rc2 == v_lc1) {
    				--rt;
    			}
    			v_lc1 = v_lc2;
    			v_rc1 = v_rc2;
    			v = fa[top[v]];
    		}
    	}
    	if (dep[u] > dep[v]) {
    		rt += qry(1, id[v], id[u], u_lc2, u_rc2);
    		if (u_rc2 == u_lc1) {
    			--rt;
    		}
    		if (u_lc2 == v_lc1) {
    			--rt;
    		}
    	}
    	else {
    		rt += qry(1, id[u], id[v], v_lc2, v_rc2);
    		if (v_rc2 == v_lc1) {
    			--rt;
    		}
    		if (v_lc2 == u_lc1) {
    			--rt;
    		}
    	}
    	return rt;
    }
    
    int main(void) {
    	//freopen("paint.in", "r", stdin);
    	//freopen("paint.out", "w", stdout);
    	memset(head, -1, sizeof head);
    	memset(next, -1, sizeof next);
    	unsigned seed;
    	scanf("%d%d", &n, &m);
    	seed += n + m;
    	for (int i = 1; i <= n; ++i) {
    		scanf("%d", ini_c + i);
    		seed += ini_c[i];
    	}
    	for (int i = 1; i < n; ++i) {
    		scanf("%d%d", &t1, &t2);
    		ist(t1, t2);
    		ist(t2, t1);
    		seed += t1;
    	}
    	
    	srand(seed);
    	root = rand() % n + 1;
    	//root = 1;
    	dfs1(root, 0);
    	dfs2(root, root);
    	make_tree(1, 1, n);
    	
    	while (m--) {
    		while ((opr = getchar()) < 'A');
    		if (opr == 'C') {
    			scanf("%d%d%d", &t1, &t2, &t3);
    			C(t1, t2, t3);
    		}
    		else {
    			scanf("%d%d", &t1, &t2);
    			printf("%d
    ", Q(t1, t2));
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    wenbao与LCIS(最长公共上升子序列)
    wenbao与cf上升序列(最多改变一个变为连续严格上升序列)
    wenbao与随机
    wenbao与cf(849D)思维
    wenbao与蓝桥
    wenbao与合肥网络赛
    wenbao与HDU
    wenbao与hiho最短路还原
    wenbao与cf连续子序列最大和问题
    wenbao与cf四个人坐车的故事
  • 原文地址:https://www.cnblogs.com/ciao-sora/p/6180473.html
Copyright © 2011-2022 走看看