bzoj2243:[SDOI2011]染色

传送门

和学长刚,说自己能不写返回值为struct的query并且不写单点查询而AC此题,挣扎了半个小时还是改回去了
直接树链剖分,对于每个节点记一下最左边的和最右边的颜色以及区间内的颜色段数,区间合并一下就好了
对于查询的时候,也合并一下,跳链的时候注意看一下两条链相邻的颜色,判断一下
这个题就没了
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void read(int &x) {
	char ch; bool ok;
	for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
	for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
const int maxn=1e5+10;char p[10];
#define rg register
int n,m,cnt,tmp,pre[maxn*2],nxt[maxn*2],h[maxn],a[maxn],dep[maxn],size[maxn],f[maxn],top[maxn],id[maxn],nid[maxn],sum;
struct oo{int l,r,ls,rs,sum,cov;}s[maxn*4];
void add(int x,int y)
{
	pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt;
	pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt;
}
void dfs(int x)
{
	size[x]=1;
	for(rg int i=h[x];i;i=nxt[i])
		if(pre[i]!=f[x])f[pre[i]]=x,dep[pre[i]]=dep[x]+1,dfs(pre[i]),size[x]+=size[pre[i]];
}
void dfs1(int x,int f)
{
	top[x]=f,id[x]=++tmp,nid[tmp]=x;int k=0;
	for(rg int i=h[x];i;i=nxt[i])
		if(dep[pre[i]]>dep[x]&&size[pre[i]]>size[k])k=pre[i];
	if(!k)return ;dfs1(k,f);
	for(rg int i=h[x];i;i=nxt[i])
		if(dep[pre[i]]>dep[x]&&pre[i]!=k)dfs1(pre[i],pre[i]);
}
void update(int x)
{
	s[x].sum=s[x<<1].sum+s[x<<1|1].sum-(s[x<<1].rs==s[x<<1|1].ls);
	s[x].ls=s[x<<1].ls;s[x].rs=s[x<<1|1].rs;
}
void build(int x,int l,int r)
{
	s[x].l=l,s[x].r=r,s[x].cov=-1;int mid=(l+r)>>1;
	if(l==r){s[x].sum=1,s[x].ls=s[x].rs=a[nid[l]];return ;}
	build(x<<1,l,mid),build(x<<1|1,mid+1,r);
	update(x);
}
void pushdown(int x)
{
	s[x<<1].cov=s[x<<1|1].cov=s[x<<1].ls=s[x<<1].rs=s[x<<1|1].ls=s[x<<1|1].rs=s[x].cov;
	s[x<<1].sum=s[x<<1|1].sum=1;s[x].cov=-1;
}
oo get(int x,int l,int r)
{
	if(l<=s[x].l&&r>=s[x].r)return s[x];
	if(s[x].cov!=-1)pushdown(x);int mid=(s[x].l+s[x].r)>>1;
	if(r<=mid)return get(x<<1,l,r);
	else if(l>mid)return get(x<<1|1,l,r);
	else 
	{
		oo a=get(x<<1,l,r),b=get(x<<1|1,l,r),c;
		c.sum=a.sum+b.sum-(a.rs==b.ls);c.ls=a.ls,c.rs=b.rs;
		return c;
	}
}
oo get(int x,int l)
{
	if(s[x].l==s[x].r)return s[x];
	if(s[x].cov!=-1)pushdown(x);int mid=(s[x].l+s[x].r)>>1;
	if(l<=mid)return get(x<<1,l);else return get(x<<1|1,l);
}
void change(int x,int l,int r,int z)
{
	if(l<=s[x].l&&r>=s[x].r){s[x].cov=z,s[x].sum=1,s[x].ls=s[x].rs=z;return ;}
	if(s[x].cov!=-1)pushdown(x);int mid=(s[x].l+s[x].r)>>1;
	if(l<=mid)change(x<<1,l,r,z);
	if(r>mid)change(x<<1|1,l,r,z);
	update(x);
}
int qsum(int x,int y)
{
	sum=0;oo a,b;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		a=get(1,id[top[x]],id[x]);sum+=a.sum;
		b=get(1,id[f[top[x]]]);sum-=(a.ls==b.rs);
		x=f[top[x]];
	}
	if(id[x]>id[y])swap(x,y);
	a=get(1,id[x],id[y]),sum+=a.sum;
	return sum;
}
void modify(int x,int y,int z)
{
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		change(1,id[top[x]],id[x],z);x=f[top[x]];
	}
	if(id[x]>id[y])swap(x,y);change(1,id[x],id[y],z);
}
int main()
{
	read(n),read(m);
	for(rg int i=1;i<=n;i++)read(a[i]);
	for(rg int i=1,x,y;i<n;i++)read(x),read(y),add(x,y);
	dfs(1),dfs1(1,1),build(1,1,n);
	for(rg int i=1,x,y,z;i<=m;i++)
	{
		scanf("%s",p+1);
		if(p[1]=='Q')read(x),read(y),printf("%d
",qsum(x,y));
		else read(x),read(y),read(z),modify(x,y,z);
	}
}
原文地址:https://www.cnblogs.com/lcxer/p/10461844.html