zoukankan      html  css  js  c++  java
  • bzoj 2243 [SDOI2011]染色

    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 8655  Solved: 3239
    [Submit][Status][Discuss]

    Description

    给定一棵有n个节点的无根树和m个操作,操作有2类:
    1、将节点a到节点b路径上所有点都染成颜色c;
    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
    如“112221”由3段组成:“11”、“222”和“1”。请你写一个程序依次完成这m个操作。

    Input

    第一行包含2个整数n和m,分别表示节点数和操作数;
    第二行包含n个正整数表示n个节点的初始颜色
    下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
    下面 行每行描述一个操作:
    “C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
    “Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

    Output

    对于每个询问操作,输出一行答案。

    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

    HINT

    数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

    Source

    第一轮day1

    Solution

    树链剖分

    线段树里面维护区间段数,区间左端点的颜色,区间右端点的颜色

    询问的时候,合并两段要看它们连接的部分是否相同,我把那个左右搞反了,因为上面的点的编号小一点,所以上面是左

    唔,最后一段要同时衔接左边段,和右边段,所以两边端点都要判断是否与最后一段相等

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define nn 100011
    using namespace std;
    int dfn[nn],wo[nn],fir[nn],nxt[nn<<1],to[nn<<1],size[nn],top[nn],fa[nn],son[nn],dep[nn],color[nn],li,e;
    struct tree{
    	int l,r,numco,lco,rco,z;
    }t[nn<<2];
    struct qu{
    	int num,lco,rco;
    }zc;
    int read()
    {
    	int ans=0,f=1;char ch=getchar();
    	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    	while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();}
    	return ans*f;
    }
    void add(int u,int v)
    {
    	nxt[++e]=fir[u];fir[u]=e;to[e]=v;       ///
    	nxt[++e]=fir[v];fir[v]=e;to[e]=u;
    }
    void dfs(int x)
    {
    	size[x]=1;
    	for(int i=fir[x];i;i=nxt[i])
    	  if(to[i]!=fa[x])
    	  {
    	  	fa[to[i]]=x;
    	  	dfs(to[i]);
    	  	if(size[to[i]]>size[son[x]])
    	  	  son[x]=to[i];
    	  	size[x]+=size[to[i]];
    	  }
    }
    void dfs2(int x)
    {
    	if(son[x])
    	{
    		dep[son[x]]=dep[x]+1;
    		dfn[++li]=son[x];
    		wo[son[x]]=li;
    		top[son[x]]=top[x];
    		dfs2(son[x]);
    	}
    	for(int i=fir[x];i;i=nxt[i])
    	  if(to[i]!=son[x]&&to[i]!=fa[x])
    	  {
    	  	dep[to[i]]=dep[x]+1;
    	  	dfn[++li]=to[i];
    	  	wo[to[i]]=li;
    	  	top[to[i]]=to[i];
    	  	dfs2(to[i]);
    	  }
    }
    void updata(int k)
    {
    	t[k].lco=t[k<<1].lco;
    	t[k].rco=t[k<<1|1].rco;
    	t[k].numco=t[k<<1].rco==t[k<<1|1].lco? t[k<<1].numco+t[k<<1|1].numco-1:t[k<<1].numco+t[k<<1|1].numco;
    }
    void build(int k,int l,int r)
    {
    	t[k].l=l;t[k].r=r;
    	if(l==r)
    	{
    		t[k].numco=1;
    		t[k].lco=color[dfn[l]];
    		t[k].rco=color[dfn[l]];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(k<<1,l,mid);
    	build(k<<1|1,mid+1,r);
    	updata(k);
    }
    void pushdown(int k)
    {
    	t[k<<1].lco=t[k].z;t[k<<1].rco=t[k].z;t[k<<1].numco=1;t[k<<1].z=t[k].z;
    	t[k<<1|1].lco=t[k].z;t[k<<1|1].rco=t[k].z;t[k<<1|1].numco=1;t[k<<1|1].z=t[k].z;
    	t[k].z=0; 
    }
    void modify(int k,int l,int r,int c)
    {
    	if(t[k].l==l&&t[k].r==r)
    	{
    		t[k].numco=1;
    		t[k].lco=c;
    		t[k].rco=c;
    		t[k].z=c;
    		return;
    	}
    	if(t[k].z)
    	  pushdown(k);
    	int mid=(t[k].l+t[k].r)>>1;
    	if(r<=mid)
    	  modify(k<<1,l,r,c);
    	else if(l>mid)
    	  modify(k<<1|1,l,r,c);
    	else
    	{
    		modify(k<<1,l,mid,c);
    		modify(k<<1|1,mid+1,r,c);
    	}
    	updata(k);
    }
    qu query(int k,int l,int r)
    {
    	if(t[k].l==l&&t[k].r==r)
    	{
    		qu o;
    		o.lco=t[k].lco;
    		o.rco=t[k].rco;
    		o.num=t[k].numco;
    		return o;
    	}
    	if(t[k].z)
    	  pushdown(k);
    	int mid=(t[k].l+t[k].r)>>1;
    	if(r<=mid)
    	  return query(k<<1,l,r);
    	else if(l>mid)
    	  return query(k<<1|1,l,r);
    	else
    	{
    		qu oo,oe;
    		oo=query(k<<1,l,mid);
    		oe=query(k<<1|1,mid+1,r);
    		oo.num+=oe.num;
    		if(oo.rco==oe.lco)
    		  oo.num--;
    		oo.rco=oe.rco;
    		return oo;
    	}
    }
    void revise(int a,int b,int c)
    {
    	while(top[a]!=top[b])
    	{
    		if(dep[top[a]]<dep[top[b]])
    		  swap(a,b);
    		modify(1,wo[top[a]],wo[a],c);
    		a=fa[top[a]];
    	}
    	if(dep[a]>dep[b])
    	  swap(a,b);
    	modify(1,wo[a],wo[b],c);
    }
    int ask(int a,int b)
    {
    	int res=0,prea=-1,preb=-1;
    	while(top[a]!=top[b])
    	{
    		if(dep[top[a]]>dep[top[b]])
    		{
    			zc=query(1,wo[top[a]],wo[a]);
    			res+=zc.num;
    			if(prea>=0&&prea==zc.rco)
    			  res--;
    			prea=zc.lco;         ///反了 
    			a=fa[top[a]];
    		}
    		else
    		{
    			zc=query(1,wo[top[b]],wo[b]);
    			res+=zc.num;
    			if(preb>=0&&preb==zc.rco)
    			  res--;
    			preb=zc.lco;
    			b=fa[top[b]];
    		}
    	}
    	if(dep[a]<dep[b])
    	{
    		zc=query(1,wo[a],wo[b]);
    		res+=zc.num;
    		if(prea>=0&&prea==zc.lco)
    		  res--;
    		if(preb>=0&&preb==zc.rco)
    		  res--;
    	}
    	else
    	{
    		zc=query(1,wo[b],wo[a]);
    		res+=zc.num;
    		if(preb>=0&&preb==zc.lco)
    		  res--;
    		if(prea>=0&&prea==zc.rco)
    		  res--;
    	}
    	return res;
    }
    int main()
    {
    	char opt;
    	int n,m,a,b,c,u,v;
    	n=read();m=read();
    	for(int i=1;i<=n;i++)
    	  color[i]=read();
    	for(int i=1;i<n;i++)
    	{
    		u=read();v=read();add(u,v);
    	}
    	dfs(1);
    	top[1]=1;
    	dep[1]=1;
    	dfn[++li]=1;wo[1]=li;
    	dfs2(1);
    	build(1,1,n);
    	for(int i=1;i<=m;i++)
    	{
    		opt=getchar();
    		while(opt!='C'&&opt!='Q')
    		  opt=getchar();
    		a=read();b=read();
    		if(opt=='C')
    		{
    			c=read();
    			revise(a,b,c);
    		}
    		else
    		  printf("%d
    ",ask(a,b));
    	}
    	return 0;
    }
  • 相关阅读:
    给div添加disabled属性
    11个让你吃惊的 Linux 终端命令
    在 Linux 平台中调试 C/C++ 内存泄漏方法(转)
    在压缩话单中过滤指定IP的一个小脚本
    过滤IP地址的正则表达式
    【转】网络编程知识
    linux下软链接与硬链接及其区别
    函数式编程入门教程(转)
    suricate学习笔记1--初步认识(转)
    lsof命令详解(转)
  • 原文地址:https://www.cnblogs.com/charlotte-o/p/7694969.html
Copyright © 2011-2022 走看看