CF620E New Year Tree 线段树 dfs序

luogu链接

题目大意:

有一个节点有颜色的树

操作1.修改子树的颜色

操作2.查询子树颜色的种类

注意,颜色种类小于60种

只有子树的操作,dfs序当然是最好的选择

dfs序列是什么,懒得讲了,自己搜吧

然后开两个数组,begin_和end_记录节点子树在dfs序数组中的开头和结尾

begin,end居然在cf是关键字,还好不是ccf,要不就死了

区间修改一个数,区间查询,线段树的傻逼操作

OK

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define ll long long
const int max4 = 2e6 + 7;
const int inf = 0x3f3f3f3f;

int n, m;
int w[max4], a[max4], begin_[max4], end_[max4];
struct node
{
    int l, r, size, lazy;
    ll z;
    void color(int i)
    {
        z = z | (1LL << (i - 1));
    }
    void clear()
    {
        z = 0LL;
    }
} e[max4];
struct edge_edge
{
    int v, nxt;
} edge[max4];
int head[max4], e_tot;

void add_edge(int u, int v)
{
    edge[++e_tot].v = v;
    edge[e_tot].nxt = head[u];
    head[u] = e_tot;
}

int count(ll z)
{
    int js = 0;
    for (; z;)
    {
        if (z & 1) js++;
        z >>= 1;
    }
    return js;
}

int read()
{
    int x = 0, f = 1; char s = getchar();
    for (; s < '0' || s > '9'; s = getchar()) if (s == '-') f = -1;
    for (; s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
    return x * f;
}

void pushup(int rt)
{
    e[rt].z = e[ls].z | e[rs].z;
}

void pushdown(int rt)
{
    if (e[rt].lazy)
    {
        e[ls].clear();
        e[rs].clear();
        e[ls].color(e[rt].lazy);
        e[rs].color(e[rt].lazy);
        e[ls].lazy = e[rt].lazy;
        e[rs].lazy = e[rt].lazy;
        e[rt].lazy = 0;
    }
}

void build(int l, int r, int rt)
{
    e[rt].l = l, e[rt].r = r;
    if (l == r)
    {
        e[rt].color(w[a[l]]);
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, ls);
    build(mid + 1, r, rs);
    pushup(rt);
}

void update(int L, int R, int k, int rt)
{
    if (L <= e[rt].l && e[rt].r <= R)
    {
        e[rt].clear();
        e[rt].color(k);
        e[rt].lazy = k;
        return;
    }
    pushdown(rt);
    int mid = (e[rt].l + e[rt].r) >> 1;
    if (L <= mid) update(L, R, k, ls);
    if (R > mid) update(L, R, k, rs);
    pushup(rt);
}

ll query(int L, int R, int rt)
{
    if (L <= e[rt].l && e[rt].r <= R)
    {
        return e[rt].z;
    }
    pushdown(rt);
    int mid = (e[rt].l + e[rt].r) >> 1;
    ll ans = 0;
    if (L <= mid) ans = ans | query(L, R, ls);
    if (R > mid) ans = ans | query(L, R, rs);
    pushup(rt);
    return ans;
}
void debug()
{
    printf("debug\n");
    printf("               %d\n", count(e[1].z));
    printf("       %d               %d\n", count(e[2].z), count(e[3].z) );
    printf("   %d       %d       %d       %d\n", count(e[4].z), count(e[5].z), count(e[6].z), count(e[7].z) );
    printf(" %d   %d   %d   %d   %d   %d   %d   %d\n", count(e[8].z),
           count(e[9].z), count(e[10].z), count(e[11].z), count(e[12].z), count(e[13].z), count(e[14].z), count(e[15].z));
}

int js;
void dfs(int u, int f)
{
    a[++js] = u;
    begin_[u] = js;
    for (int i = head[u]; i; i = edge[i].nxt)
    {
        int v = edge[i].v;
        if (v == f) continue;
        dfs(v, u);
    }
    end_[u] = js;
}

int main()
{
    n = read(), m = read();
    for (int i = 1; i <= n; ++i)
    {
        w[i] = read();
    }
    for (int i = 1; i < n; ++i)
    {
        int x = read(), y = read();
        add_edge(x, y);
        add_edge(y, x);
    }
    dfs(1, 0);
    // cout << js << "\n";
    // for (int i = 1; i <= n; ++i)
    // {
    // 	printf("%d ", a[i]);
    // } puts("");
    // for (int i = 1; i <= n; ++i)
    // {
    // 	printf("%d => %d~~%d\n", i, begin_[i], end_[i]);
    // }
    build(1, n, 1);
    for (int i = 1; i <= m; ++i)
    {
        int tmp = read();
        if (tmp == 1)
        {
            int a = read(), b = read();
            update(begin_[a], end_[a], b, 1);
        }
        else
        {
            int a = read();
            ll ans = query(begin_[a], end_[a], 1);
            printf("%d\n", count(ans));
        }
        //debug();
    }
    return 0;
}

posted @ 2018-10-09 06:19  ComplexPug  阅读(150)  评论(0编辑  收藏  举报