zoukankan      html  css  js  c++  java
  • 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
    ");
        printf("               %d
    ", count(e[1].z));
        printf("       %d               %d
    ", count(e[2].z), count(e[3].z) );
        printf("   %d       %d       %d       %d
    ", 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
    ", 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 << "
    ";
        // for (int i = 1; i <= n; ++i)
        // {
        // 	printf("%d ", a[i]);
        // } puts("");
        // for (int i = 1; i <= n; ++i)
        // {
        // 	printf("%d => %d~~%d
    ", 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
    ", count(ans));
            }
            //debug();
        }
        return 0;
    }
    
    
  • 相关阅读:
    用Fragment实现如新浪微博一样的底部菜单的切换
    Android基础之使用Fragment控制切换多个页面
    Android_Fragment_Fragment详解
    android下拉菜单spinner的使用方法
    eclipse / ADT(Android Develop Tool) 一些方便的初始设置
    Android Studio如何设置代码自动提示
    <交流贴>android语音识别之科大讯飞语音API的使用
    原 [Android]LIstView的HeaderView
    001 Java 深拷贝、浅拷贝及Cloneable接口
    GenericServlet与HttpServlet
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/9758243.html
Copyright © 2011-2022 走看看