• Luogu P2486 [SDOI2011]染色


    gate

    还算好想的一个树链剖分+线段树...

    修改一段路径的颜色直接区间修改即可。
    询问颜色段数量时,线段树的每个节点记录这一段有多少个颜色段。
    pushup和query时要检查mid和mid+1是否颜色相同,
    例如sum[now] = sum[ls] + sum[rs] - (col[mid]==col[mid+1])
    递归路径时要检查top[x]和fa[top[x]](两条路径的交界处)是否颜色相同,但这里需要单独写一个函数getc()来查找这两个点的颜色,
    ans += query(dfn[top[x]],dfn[x]...) - ( getc(dfn[top[x]]...) == getc(dfn[fa[top[x]]]...) )

    初始建树时,定义col[l] = w[po[l]](po即dfn所对应的原来序号)
    modify的时候也需要pushdown一下

    当然也可以不用col数组,用lc,rc来记录某点的左右端点的颜色,不过劣势是要开4倍空间。

    代码如下

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #define MogeKo qwq
    using namespace std;
    
    const int maxn = 4e5+10;
    
    int n,m,x,y,z,cnt,num;
    char op[10];
    
    int head[maxn],to[maxn],nxt[maxn];
    
    int w[maxn],sum[maxn],col[maxn],lazy[maxn];
    int dpth[maxn],siz[maxn],fa[maxn],hson[maxn];
    int dfn[maxn],top[maxn],po[maxn];
    
    void add(int x,int y) {
    	to[++cnt] = y;
    	nxt[cnt] = head[x];
    	head[x] = cnt;
    }
    
    void dfs1(int u) {
    	dpth[u] = dpth[fa[u]]+1;
    	siz[u] = 1;
    	for(int i = head[u]; i; i = nxt[i]) {
    		int v = to[i];
    		if(v == fa[u]) continue;
    		fa[v] = u;
    		dfs1(v);
    		siz[u] += siz[v];
    		if(siz[v] > siz[hson[u]]) hson[u] = v;
    	}
    }
    
    void dfs2(int u,int t) {
    	dfn[u] = ++num;
    	po[num] = u;
    	top[u] = t;
    	if(!hson[u]) return;
    	dfs2(hson[u],t);
    	for(int i = head[u]; i; i = nxt[i]) {
    		int v = to[i];
    		if(v == fa[u] || v == hson[u]) continue;
    		dfs2(v,v);
    	}
    }
    
    #define sora suki
    #define Mid ((l+r)>>1)
    #define lson (now<<1)
    #define rson (now<<1|1)
    
    void pushup(int mid,int now) {
    	sum[now] = sum[lson] + sum[rson] - (col[mid] == col[mid+1]);
    	lazy[now] = 0;
    }
    
    void build(int l,int r,int now) {
    	if(l == r) {
    		sum[now] = 1;
    		col[l] = w[po[l]];
    		return;
    	}
    	int mid = Mid;
    	build(l,mid,lson);
    	build(mid+1,r,rson);
    	pushup(mid,now);
    }
    
    void pushdown(int mid,int now) {
    	if(!lazy[now]) return;
    	lazy[lson] = lazy[rson] = col[mid] = col[mid+1] = lazy[now];
    	sum[lson] = sum[rson] = 1;
    	lazy[now] = 0;
    }
    
    void modify(int L,int R,int l,int r,int now,int c) {
    	if(L <= l && r <= R) {
    		lazy[now] = col[l] = col[r] = c;
    		sum[now] = 1;
    		return;
    	}
    	int mid = Mid;
    	pushdown(mid,now);
    	if(L <= mid) modify(L,R,l,mid,lson,c);
    	if(R >= mid+1) modify(L,R,mid+1,r,rson,c);
    	pushup(mid,now);
    }
    
    int query(int L,int R,int l,int r,int now) {
    	if(L <= l && r <= R) return sum[now];
    	int mid = Mid;
    	pushdown(mid,now);
    	if(R <= mid) return query(L,R,l,mid,lson);
    	else if(L >= mid+1) return query(L,R,mid+1,r,rson);
    	else return query(L,R,l,mid,lson) + query(L,R,mid+1,r,rson) - (col[mid] == col[mid+1]);
    }
    
    int getcol(int l,int r,int now,int k) {
    	if(lazy[now]) return lazy[now];
    	int mid = Mid;
    	pushdown(mid,now);
    	if(l == r) return col[l];
    	if(k <= mid) return getcol(l,mid,lson,k);
    	else if(k >= mid+1) return getcol(mid+1,r,rson,k);
    }
    
    int getmodify(int x,int y,int c) {
    	while(top[x] != top[y]) {
    		if(dpth[top[x]] < dpth[top[y]]) swap(x,y);
    		modify(dfn[top[x]],dfn[x],1,n,1,c);
    		x = fa[top[x]];
    	}
    	if(dpth[x] > dpth[y]) swap(x,y);
    	modify(dfn[x],dfn[y],1,n,1,c);
    }
    
    int getquery(int x,int y) {
    	int ans = 0;
    	while(top[x] != top[y]) {
    		if(dpth[top[x]] < dpth[top[y]])	swap(x,y);
    		ans += 	query(dfn[top[x]],dfn[x],1,n,1);
    		ans -= (getcol(1,n,1,dfn[top[x]]) == getcol(1,n,1,dfn[fa[top[x]]]));
    		x = fa[top[x]];
    	}
    	if(dpth[x] > dpth[y]) swap(x,y);
    	ans += query(dfn[x],dfn[y],1,n,1);
    	return ans;
    }
    
    int main() {
    	scanf("%d%d",&n,&m);
    	for(int i = 1; i <= n; i++)
    		scanf("%d",&w[i]);
    	for(int i = 1; i <= n-1; i++) {
    		scanf("%d%d",&x,&y);
    		add(x,y), add(y,x);
    	}
    	dfs1(1);
    	dfs2(1,1);
    	build(1,n,1);
    //	for(int i = 1; i <= n; i++)
    //		col[i] = w[po[i]];
    	while(m--) {
    		scanf("%s",op);
    		scanf("%d%d",&x,&y);
    		if(op[0] == 'C') {
    			scanf("%d",&z);
    			getmodify(x,y,z);
    		}
    		if(op[0] == 'Q')
    			printf("%d
    ",getquery(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    css居中问题(转)
    Request.ServerVariables 各个参数的用法
    html5 画个球碰撞
    递归生成json
    AspNetPager分页结合存储过程的用法
    sql+aspnetpager+查询功能
    求1+2+……+n
    几种排序的比较 bitmapsort,qsort,set
    利用两个栈,反转其中一个栈的元素
    进程间通信(IPC, Inter Process Communication)读书笔记
  • 原文地址:https://www.cnblogs.com/mogeko/p/12556759.html
Copyright © 2020-2023  润新知