Codeforces 620E - New Year Tree 【DFS序+线段树】


E. New Year Tree

time limit per test   3seconds

memory limit per test      256megabytes

The New Year holidays are over, but Resha doesn't want to throw away the New Year tree. He invited his best friendsKerim and Gural to help him to redecorate the New Year tree.

The New Year tree is an undirected tree with n vertices androot in the vertex 1.

You should process the queries of the two types:

1. Change thecolours of all vertices in the subtree of the vertex v to the colour c.

2. Find the numberof different colours in the subtree of the vertex v.

Input

The first line contains two integers n, m (1 ≤ n, m ≤ 4·105) — the numberof vertices in the tree and the number of the queries.

The second line contains n integers ci (1 ≤ ci ≤ 60) — the colourof the i-th vertex.

Each of the next n - 1 lines containstwo integers xj, yj (1 ≤ xj, yj ≤ n) — the verticesof the j-th edge. It isguaranteed that you are given correct undirected tree.

The last m lines contains the description of thequeries. Each description starts with the integer tk (1 ≤ tk ≤ 2) — the type ofthe k-th query. Forthe queries of the first type then follows two integers vk, ck (1 ≤ vk ≤ n, 1 ≤ ck ≤ 60) — the numberof the vertex whose subtree will be recoloured with the colour ck. For thequeries of the second type then follows integer vk (1 ≤ vk ≤ n) — the numberof the vertex for which subtree you should find the number of differentcolours.

Output

For each query of the second type printthe integer a — the number ofdifferent colours in the subtree of the vertex given in the query.

Each of the numbers should be printed on a separate linein order of query appearing in the input.

Examples

Input

7 10
1 1 1 1 1 1 1
1 2
1 3
1 4
3 5
3 6
3 7
1 3 2
2 1
1 4 3
2 1
1 2 5
2 1
1 6 4
2 1
2 2
2 3

Output

2
3
4
5
1
2

Input

23 30
1 2 2 6 5 3 2 1 1 1 2 4 5 3 4 4 3 3 3 3 3 4 6
1 2
1 3
1 4
2 5
2 6
3 7
3 8
4 9
4 10
4 11
6 12
6 13
7 14
7 15
7 16
8 17
8 18
10 19
10 20
10 21
11 22
11 23
2 1
2 5
2 6
2 7
2 8
2 9
2 10
2 11
2 4
1 12 1
1 13 1
1 14 1
1 15 1
1 16 1
1 17 1
1 18 1
1 19 1
1 20 1
1 21 1
1 22 1
1 23 1
2 1
2 5
2 6
2 7
2 8
2 9
2 10
2 11
2 4

Output

6
1
3
3
2
1
2
3
5
5
1
2
2
1
1
1
2
3

 


【题目链接】 link

【题意】

给出一棵树,树上每个节点都有一种颜色,现在有两种操作,一种是把以x为根的子树都染成某一种颜色,第二种操作是询问以x为根的子树有几种颜色。

【思路】

由于颜色最多只有60种,考虑利用二进制压位

又因为每次处理都是针对子树,所以自然想到用dfs序。

我们先处理出的dfs序,然后再利用dfs序把颜色对应到线段树上。tree数组表示的即为以其为根的子树的颜色状态。

修改时直接打一下颜色标记(类似于原来的flag),然后pushup,pushdown。

查询时,把所有情况都或起来,最后算一下,二进制表示中1的个数即为答案


#include <cstdio>
#include <bits/stdc++.h>
#include <cmath>
#include <map>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long ll;
const int maxn = 400005;
const int mod = 10007;
const ll INF = 1e18;
const double eps = 1e-6;

int n,m,tot,cnt;
int color[maxn];
int head[maxn];
int le[maxn],ri[maxn],flag[maxn<<2],num[maxn];
ll tree[maxn<<2];

struct node
{
    int v,next;
}e[maxn<<2];

void add(int u,int v)
{
    e[tot].v=v;
    e[tot].next=head[u];
    head[u]=tot++;
}

void init()
{
    tot=cnt=0;
    mst(head,-1);
}

void dfs(int u,int pre)
{
    le[u]=++cnt;
    num[cnt]=u;
    for(int i=head[u];~i;i=e[i].next)
    {
        int v=e[i].v;
        if(v==pre) continue;
        dfs(v,u);
    }
    ri[u]=cnt;
}

void pushup(int rt)
{
    tree[rt]=tree[rt<<1]|tree[rt<<1|1];
}

void pushdown(int rt)
{
    if(flag[rt])
    {
        flag[rt<<1]=flag[rt<<1|1]=flag[rt];
        tree[rt<<1]=tree[rt<<1|1]=(1LL<<flag[rt]);
        flag[rt]=0;
    }
}

void build(int l,int r,int rt)
{
    flag[rt]=0;
    if(l==r)
    {
        tree[rt]=(1LL<<color[num[l]]);
        return;
    }
    int m=(l+r)/2;
    build(lson);
    build(rson);
    pushup(rt);
}

void update(int L,int R,int val,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        tree[rt]=(1LL<<val);
        flag[rt]=val;
        return;
    }
    int m=(l+r)/2;
    pushdown(rt);
    if(L<=m) update(L,R,val,lson);
    if(m<R) update(L,R,val,rson);
    pushup(rt);
}

ll query(int L,int R,int l,int r,int rt)
{
    if(L>r||R<l) return 0;
    if(L<=l&&r<=R) return tree[rt];
    int m=(l+r)/2;
    pushdown(rt);
    return query(L,R,lson)|query(L,R,rson);
}

int main()
{
    scanf("%d%d",&n,&m);
    init();
    for(int i=1;i<=n;i++) scanf("%d",&color[i]);
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(1,-1);
    build(1,n,1);
    while(m--)
    {
        int op,x,y;
        scanf("%d%d",&op,&x);
        if(op==1)
        {
            scanf("%d",&y);
            update(le[x],ri[x],y,1,n,1);
        }
        else
        {
            ll tmp=query(le[x],ri[x],1,n,1);
            int ans=0;
            while(tmp)
            {
                ans+=tmp%2;
                tmp/=2;
            }
            printf("%d\n",ans);
        }
    }
}








发布了259 篇原创文章 · 获赞 100 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/my_sunshine26/article/details/79937404