zoukankan      html  css  js  c++  java
  • 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);
    	}
    }
    
  • 相关阅读:
    ANSYS Workbench 16.0超级学习手册(附光盘)
    自控力(套装共2册)
    超实用记忆力训练法
    大愿法师“幸福人生”系列丛书——禅心商道
    高情商沟通术(写给所有深受社交困扰的人)
    青年职业形象管理手册(高等职业教育在线开放课程新形态一体化规划教材)
    1019. 括号匹配
    1026. 高精度除法
    1018. A+B Problem Revisited
    1015. 高精度乘法
  • 原文地址:https://www.cnblogs.com/lcxer/p/10461844.html
Copyright © 2011-2022 走看看