zoukankan      html  css  js  c++  java
  • bzoj-2243 染色

    题意:

    给出一个无根树和树上每一个结点的初始颜色。

    然后进行m次操作;

    C:将x到y的路径全部点染成某个颜色;

    Q:查询x到y的路径上经过多少个颜色块;

    n,m<=10^5;


    题解:

    挺裸的树链剖分,改动的时候要用延迟标记维护。

    可是注意颜色可能为0,所以我单独开了一个bool的数组维护是否有标记;

    在合并两个区间的时候要推断两个端点的颜色是否同样;

    假设同样要将端点合并,也就是答案-1;

    在树链间切换的时候也是要查一下端点;


    然后我就WA了!

    之后查啊查。查啊查。

    发现我模板敲错了!我还认为那是对的。。。

    和曾经的代码对照才发现不正确啊啊啊啊

    就是在类似LCA的过程中交换x,y推断的是deep[top[x]]<deep[top[y]]。

    我写成了deep[x]<deep[y];

    发现博客里没有树剖就写一发传上来以后当模板抄抄= =。


    代码:


    #include<vector>
    #include<math.h>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 110000
    #define lson l,mid,no<<1
    #define rson mid+1,r,no<<1|1
    using namespace std;
    vector<int>to[N];
    int a[N], fa[N], ch[N], size[N], top[N], deep[N];
    int p[N], rank[N], cov[N << 2], L[N << 2], R[N << 2], sum[N << 2], n, tot;
    bool is[N << 2];
    char str[10];
    void dfs1(int x, int d, int pre)
    {
    	deep[x] = d, fa[x] = pre, size[x] = 1;
    	int i, y;
    	for (i = 0; i < to[x].size(); i++)
    	{
    		if ((y = to[x][i]) != pre)
    		{
    			dfs1(y, d + 1, x);
    			size[x] += size[y];
    			if (size[y]>size[ch[x]])
    				ch[x] = y;
    		}
    	}
    }
    void dfs2(int x, int t)
    {
    	top[x] = t;
    	p[x] = ++tot;
    	rank[tot] = x;
    	if (ch[x])
    		dfs2(ch[x], t);
    	int i, y;
    	for (i = 0; i < to[x].size(); i++)
    	{
    		y = to[x][i];
    		if (y != fa[x] && y != ch[x])
    			dfs2(y, y);
    	}
    }
    void Pushup(int no)
    {
    	L[no] = L[no << 1], R[no] = R[no << 1 | 1];
    	sum[no] = sum[no << 1] + sum[no << 1 | 1] -(R[no << 1] == L[no << 1 | 1]);
    }
    void Pushdown(int no)
    {
    	if (is[no])
    	{
    		sum[no << 1] = sum[no << 1 | 1] = 1;
    		is[no << 1] = is[no << 1 | 1] = 1;
    		cov[no << 1] = cov[no << 1 | 1] = cov[no];
    		L[no << 1] = R[no << 1] = L[no << 1 | 1] = R[no << 1 | 1] = cov[no];
    		cov[no] = is[no] = 0;
    	}
    }
    void Build(int l, int r, int no)
    {
    	if (l == r)
    		L[no] = R[no] = a[rank[l]],
    		sum[no] = 1;
    	else
    	{
    		int mid = (l + r) >> 1;
    		Build(lson);
    		Build(rson);
    		Pushup(no);
    	}
    }
    void update(int l, int r, int no, int st, int en, int v)
    {
    	if (st <= l&&r <= en)
    	{
    		L[no] = R[no] = v;
    		cov[no] = v;
    		sum[no] = 1;
    		is[no] = 1;
    	}
    	else
    	{
    		int mid = (l + r) >> 1;
    		Pushdown(no);
    		if (en <= mid)		update(lson, st, en, v);
    		else if (st > mid)	update(rson, st, en, v);
    		else		update(lson, st, en, v), update(rson, st, en, v);
    		Pushup(no);
    	}
    }
    int get(int l, int r, int no, int k)
    {
    	if (l == r)
    		return L[no];
    	else
    	{
    		int mid = (l + r) >> 1;
    		Pushdown(no);
    		if (k <= mid)	return get(lson, k);
    		else			return get(rson, k);
    	}
    }
    int query(int l, int r, int no, int st, int en)
    {
    	if (st <= l&&r <= en)
    		return sum[no];
    	else
    	{
    		int mid = (l + r) >> 1;
    		Pushdown(no);
    		if (en <= mid)		return query(lson, st, en);
    		else if (st > mid)	return query(rson, st, en);
    		else
    		{
    			int ret = query(lson, st, en) + query(rson, st, en);
    			if (R[no << 1] == L[no << 1 | 1])
    				ret--;
    			return ret;
    		}
    	}
    }
    void op_C(int x, int y, int v)
    {
    	while (top[x] != top[y])
    	{
    		if (deep[top[x]] < deep[top[y]])	swap(x, y);
    		update(1, n, 1, p[top[x]], p[x], v);
    		x = fa[top[x]];
    	}
    	if (deep[x] < deep[y])	swap(x, y);
    	update(1, n, 1, p[y], p[x], v);
    }
    int op_Q(int x, int y)
    {
    	int ret = 0;
    	while (top[x] != top[y])
    	{
    		if (deep[top[x]] < deep[top[y]])	swap(x, y);
    		ret += query(1, n, 1, p[top[x]], p[x]);
    		if (get(1, n, 1, p[top[x]]) == get(1, n, 1, p[fa[top[x]]]))
    			ret--;
    		x = fa[top[x]];
    	}
    	if (deep[x] < deep[y])	swap(x, y);
    	ret += query(1, n, 1, p[y], p[x]);
    	return ret;
    }
    int main()
    {
    	int m, i, j, k, x, y, v;
    	scanf("%d%d", &n, &m);
    	for (i = 1; i <= n; i++)
    		scanf("%d", a + i);
    	for (i = 1; i < n; i++)
    	{
    		scanf("%d%d", &x, &y);
    		to[x].push_back(y);
    		to[y].push_back(x);
    	}
    	dfs1(1, 1, 0);
    	dfs2(1, 0);
    	Build(1, n, 1);
    	for (i = 1; i <= m; i++)
    	{
    		scanf("%s", str);
    		if (str[0] == 'C')
    		{
    			scanf("%d%d%d", &x, &y, &v);
    			op_C(x, y, v);
    		}
    		else
    		{
    			scanf("%d%d", &x, &y);
    			printf("%d
    ", op_Q(x, y));
    		}
    	}
    	return 0;
    }
    


  • 相关阅读:
    如何批量修改文件名
    iphone数据存储之-- Core Data的使用(一)
    ios中@class和 #import,两种方式的讨论
    #import与@class的区别
    第三方Push服务:Urban Airship
    iOS开发如何实现消息推送机制
    cocos2d-x中CCCallFunc CCCallFuncN CCCallFuncND的区别和使用示例
    纯Html+Ajax和JSP两者的优缺点
    什么是Ajax?
    解读前端开发工程师必备技能
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7118580.html
Copyright © 2011-2022 走看看