• bzoj2243[SDOI2011] 染色


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 (权限题..)

    题目大意:

    给定一棵有n个节点的无根树和m个操作,操作有2类:
    1、将节点a到节点b路径上所有点都染成颜色c;
    2、询问节点a到节点b路径上的颜色段数量

    把样例贴一下好了..

     //一开始读入每个点的初始颜色

    Sample Input
    6 5
    2 2 1 2 1 1
    1 2
    1 3
    2 4
    2 5
    2 6
    Q 3 5
    C 2 1 1
    Q 3 5
    C 5 1 2
    Q 3 5

    Sample Output
    3
    1
    2


    题解:树剖..记录左右孩子的颜色以防统计颜色出错,真的很容易错.. (可以LCT..还没用LCT做一遍

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define maxn 101000
    
    struct node
    {
    	int x,y,c,next;
    }a[maxn*2];
    int len,first[maxn];
    struct tree
    {
    	int l,r,lc,rc,lm,rm,sum,la;
    }tr[maxn*2];int trlen;
    int dep[maxn],fa[maxn],son[maxn];
    int z,tot[maxn],top[maxn],ys[maxn];
    void ins(int x,int y)
    {
    	len++;
    	a[len].x=x;a[len].y=y;
    	a[len].next=first[x];first[x]=len;
    }
    void dfs1(int x)
    {
    	son[x]=0;tot[x]=1;
    	for (int k=first[x];k!=-1;k=a[k].next)
    	{
    		int y=a[k].y;
    		if (y!=fa[x])
    		{
    			fa[y]=x;
    			dep[y]=dep[x]+1;
    			dfs1(y);
    			if (tot[son[x]]<tot[y]) son[x]=y;
    			tot[x]+=tot[y];
    		}
    	}
    }
    void dfs2(int x,int tp)
    {
    	ys[x]=++z;top[x]=tp;
    	if (son[x]!=0) dfs2(son[x],tp);
    	for (int k=first[x];k!=-1;k=a[k].next)
    	{
    		int y=a[k].y;
    		if (y!=fa[x] && y!=son[x]) dfs2(y,y);
    	}
    }
    void bt(int l,int r)
    {
    	trlen++;int now=trlen;
    	tr[now].l=l;tr[now].r=r;
    	tr[now].lc=tr[now].rc=-1;
    	tr[now].lm=tr[now].rm=-1;
    	tr[now].sum=0;tr[now].la=-1;
    	if (l<r)
    	{
    		int mid=(l+r)>>1;
    		tr[now].lc=trlen+1;bt(l,mid);
    		tr[now].rc=trlen+1;bt(mid+1,r);
    	}
    }
    void updata(int now,int lc,int rc)
    {
    	if (tr[now].la!=-1)
    	{
    		if (lc!=-1)
    		{
    			tr[lc].lm=tr[lc].rm=tr[now].la;
    			tr[lc].sum=1;tr[lc].la=tr[now].la;
    		}
    		if (rc!=-1)
    		{
    			tr[rc].lm=tr[rc].rm=tr[now].la;
    			tr[rc].sum=1;tr[rc].la=tr[now].la;
    		}tr[now].la=-1;
    	}
    }
    void change(int now,int l,int r,int k)
    {
    	if (tr[now].l==l && tr[now].r==r)
    	{
    		tr[now].lm=tr[now].rm=k;
    		tr[now].sum=1;tr[now].la=k;
    		return;
    	}int mid=(tr[now].l+tr[now].r)>>1,lc=tr[now].lc,rc=tr[now].rc;
    	updata(now,lc,rc);
    	if (r<=mid) change(lc,l,r,k);
    	else if (l>mid) change(rc,l,r,k);
    	else change(lc,l,mid,k),change(rc,mid+1,r,k);
    	tr[now].lm=tr[lc].lm;
    	tr[now].rm=tr[rc].rm;
    	tr[now].sum=tr[lc].sum+tr[rc].sum;
    	if (tr[lc].rm==tr[rc].lm) tr[now].sum--;
    }
    int LM,RM;
    int findsum(int now,int l,int r,int L,int R)
    {
    	if (tr[now].l==L) LM=tr[now].lm;
    	if (tr[now].r==R) RM=tr[now].rm;
    	if (tr[now].l==l && tr[now].r==r) return tr[now].sum;
    	int mid=(tr[now].l+tr[now].r)>>1,lc=tr[now].lc,rc=tr[now].rc;
    	updata(now,lc,rc);
    	if (r<=mid) return findsum(lc,l,r,L,R);
    	else if (l>mid) return findsum(rc,l,r,L,R);
    	else
    	{
    		int ans;
    		ans=findsum(lc,l,mid,L,R)+findsum(rc,mid+1,r,L,R);
    		if (tr[lc].rm==tr[rc].lm) ans--;
    		return ans;
    	}
    }
    void shift(int x,int y,int c)
    {
    	int tx=top[x],ty=top[y];
    	while (tx!=ty)
    	{
    		if (dep[tx]>dep[ty])
    		{
    			int tt=x;x=y;y=tt;
    			tt=tx;tx=ty;ty=tt;
    		}
    		change(1,ys[ty],ys[y],c);
    		y=fa[ty];ty=top[y];
    	}
    	if (dep[x]>dep[y])
    	{
    		int tt=x;x=y;y=tt;
    	}change(1,ys[x],ys[y],c);
    }
    int query(int x,int y)
    {
    	int tx=top[x],ty=top[y],ans=0;
    	int a1=-1,a2=-1;
    	while (tx!=ty)
    	{
    		if (dep[tx]>dep[ty])
    		{
    			int tt=x;x=y;y=tt;
    			tt=tx;tx=ty;ty=tt;
    			tt=a1;a1=a2;a2=tt;
    		}
    		ans+=findsum(1,ys[ty],ys[y],ys[ty],ys[y]);
    		if (a1==RM) ans--;a1=LM;
    		y=fa[ty];ty=top[y];
    	}
    	if (dep[x]>dep[y])
    	{
    		int tt=x;x=y;y=tt;
    		tt=a1;a1=a2;a2=tt;
    	}ans+=findsum(1,ys[x],ys[y],ys[x],ys[y]);
    	if (a1==RM) ans--;
    	if (a2==LM) ans--;
    	return ans;
    }
    int col[maxn];
    int main()
    {
    	//freopen("a.in","r",stdin);
    	//freopen("a.out","w",stdout);
    	int n,m,i,x,y,c;char s[5];
    	scanf("%d%d",&n,&m);
    	len=0;memset(first,-1,sizeof(first));
    	trlen=0;bt(1,n);
    	for (i=1;i<=n;i++)
    		scanf("%d",&col[i]);
    	for (i=1;i<n;i++)
    	{
    		scanf("%d%d",&x,&y);
    		ins(x,y);ins(y,x);
    	}
    	fa[1]=0;dep[1]=0;dfs1(1);
    	z=0;dfs2(1,1);
    	for (i=1;i<=n;i++) 
    	 change(1,ys[i],ys[i],col[i]);
    	while (m--)
    	{
    		scanf("
    %s%d%d",s,&x,&y);
    		if (s[0]=='C')
    		{
    			scanf("%d",&c);
    			shift(x,y,c);
    		}else if (s[0]=='Q')
    		{
    			printf("%d
    ",query(x,y));
    		}
    	}
    	return 0;
    }


  • 相关阅读:
    C89和C99区别--简单总结
    C语言 值传递和地址传递
    对于.h文件和.c文件
    C语言-------多文件编译
    数据结构之第二章线性表
    数据结构之第一章一些概念
    JS-prototype的掌握
    JS-return的使用
    分分钟搞懂JS-闭包函数
    JS-面向对象-封装
  • 原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527870.html
Copyright © 2020-2023  润新知