zoukankan      html  css  js  c++  java
  • [CodeForces620E] New Year Tree

    原题网址:http://codeforces.com/problemset/problem/620/E

    啊,从这篇博客开始我就不复制题目了,毕竟大家点进来都是为了我的AC代码。

    好的,这道题的题目大意就是,有一棵树,给它染色,刚开始的颜色是给定的,然后有两个操作:

    1,输入v,x,将v和其所有子节点染色成x;

    2,输入x,输出x的所有子节点的染色种类;

    很显然,这个输入和输出的方式很有区间的味道(行家啊~

    于是,我们考虑到dfs序,可以把一棵树降维到一维;

    然后,我就写了一个朴素的欧拉序(节点进出的时候记录进dfs_num数组)

    然后,,,我要怎么数颜色???

    瞄了一眼数据范围,最多60种颜色,这明白着提醒我:放心吧,随便开数组,不会mle的~

    //在教练的提醒下我选择了状压

    把每种颜色作为二进制下的一位,比如(1000)2就表示这个节点有3号颜色;

    区间合并的时候,就按位或一下,比如表示颜色三的(1000)和表示颜色二的(100)按位或后就是(1100)表示既有三又有二;

    如果有多种颜色的时候,这种方法可以起到有效的去重(这让本打算开60个数组的我情何以堪

    于是代码就出来了

    漂亮得TLE了。。。

    然后优化就是把欧拉序改成了前序遍历,就AC了

    下面放AC代码

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #define maxn 400005
    using namespace std;
    inline void read(int &x)
    {
    	x=0;int f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	x*f;
    }
    inline void read(long long &x)
    {
    	x=0;int f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	x*f;
    }
    int N,M;
    long long color_v[maxn];
    long long bas=1;
    struct node{
    	int nex,to;
    }edge[maxn<<2];
    int head[maxn],tot;
    inline void insert(int from,int to)
    {
    	tot++;
    	edge[tot].nex=head[from];
    	head[from]=tot;
    	edge[tot].to=to;
    }
    long long st[maxn],ed[maxn],dfs_num[maxn],t;
    void dfs(int x,int u)
    {
    	//cout<<"dfs note: "<<x<<" "<<t<<endl;
    	//cout<<x<<" ";
    	st[x]=++t;
    	dfs_num[t]=color_v[x];
    	for(int i=head[x];i;i=edge[i].nex)
    	{
    		if(edge[i].to!=u)
    		{
    			dfs(edge[i].to,x);
    		}
    	}
    	ed[x]=t;
    	//cout<<x<<" ";
    }
    struct tree{
    	int l,r;
    	long long color;
    }tree[maxn<<4];
    int bit(long long i)
    {
    	int ans=0;
    	while(i)
    	{
    		ans+=i&1;
    		i>>=1;
    	}
    	return ans;
    }
    void push_up(int rt)
    {
    	tree[rt].color=tree[rt<<1].color|tree[rt<<1|1].color;
    }
    void push_down(int rt)
    {
    	tree[rt<<1].color=tree[rt].color;
    	tree[rt<<1|1].color=tree[rt].color;
    }
    void build(int rt,int l,int r)
    {
    	tree[rt].l=l;
    	tree[rt].r=r;
    	if(l==r)
    	{
    		tree[rt].color=bas<<dfs_num[l];
    		return ;
    	}
    	int mid=l+r>>1;
    	build(rt<<1,l,mid);
    	build(rt<<1|1,mid+1,r);
    	push_up(rt);
    }
    void update(int rt,int l,int r,int col)
    {
    	if(tree[rt].l>r||tree[rt].r<l)
    		return ;
    	if(tree[rt].l>=l&&tree[rt].r<=r)
    	{
    		tree[rt].color=bas<<col;
    		return ;
    	}
    	if(bit(tree[rt].color)==1)
    		push_down(rt);
    	int mid=tree[rt].l+tree[rt].r>>1;
    	if(l<=mid)
    		update(rt<<1,l,r,col);
    	if(r>mid)
    		update(rt<<1|1,l,r,col);
    	push_up(rt);
    }
    long long query(int rt,int l,int r)
    {
    	if(tree[rt].l>r||tree[rt].r<l)
    		return 0;
    	if(tree[rt].l>=l&&tree[rt].r<=r)
    	{
    		return tree[rt].color;
    	}	
    	if(tree[rt].l==tree[rt].r)
    		return 0;
    	if(bit(tree[rt].color)==1)
    		push_down(rt);
    	int mid=tree[rt].l+tree[rt].r>>1;
    	long long ans=0;
    	if(l<=mid)
    	{
    		ans|=query(rt<<1,l,r);
    	}
    	/*if(ans==(1<<23))
    		cout<<"LEFT ERROR:  "<<tree[rt].l<<" "<<tree[rt].r<<endl;*/	
    	if(r>mid)
    	{
    		ans|=query(rt<<1|1,l,r);
    	}	
    	return ans;
    }
    /*void search(long long rt)
    {
    	if(bit(tree[rt].color)==1)
    	{
    		for(long long i=tree[rt].l;i<=tree[rt].r;i++)
    			cout<<log2(tree[rt].color)<<" ";
    		return ;
    	}
    	search(rt<<1);
    	search(rt<<1|1);
    }*/
    int main()
    {
    	read(N);read(M);
    	for(int i=1;i<=N;i++)
    	{
    		read(color_v[i]);
    	}
    	int u;
    	int v;
    	for(int i=1;i<N;i++)
    	{
    		read(u);read(v);
    		insert(u,v);
    		insert(v,u);
    	}
    	//cout<<"dfs note: ";
    	dfs(1,1);
    	//cout<<endl;
    	build(1,1,t);
    	int op;
    	for(int i=1;i<=M;i++)
    	{
    		//cout<<"lin note: ";
    		//search(1);
    		//cout<<endl;
    		read(op);
    		if(op==1)
    		{
    			read(u);read(v);
    			update(1,st[u],ed[u],v);
    		}
    		else
    		{
    			read(u);
    			//cout<<"check :"<<st[u]<<" "<<ed[u]<<endl;
    			printf("%d
    ",bit(query(1,st[u],ed[u])));
    		}
    	}
    }
    /*
    10 10
    23 25 23 42 23 53 49 40 28 44
    1 7
    1 2
    2 4
    4 10
    8 10
    6 8
    3 8
    5 3
    9 5
    2 10
    1 6 52
    1 8 43
    2 3
    
    */
  • 相关阅读:
    ubuntu怎么安装下载工具uget+aria2 for firefox
    #pragma once
    opencv3在CMakeLists.txt中的调用问题
    opencv之Mat数据类型
    windows10下笔记本电脑外接显示器设置
    ubuntu16.04下笔记本电脑扩展双屏安装过程
    【问题收录】Ubuntu14.04连接两个双显示器失败的解决方案
    获取jsapi_ticket
    微信公众号中高德地图显示路线开发
    微信公众号中高德地图显示路线
  • 原文地址:https://www.cnblogs.com/sherrlock/p/9525783.html
Copyright © 2011-2022 走看看