zoukankan      html  css  js  c++  java
  • CodeForces 375D Tree and Queries

    传送门:https://codeforces.com/problemset/problem/375/D

    题意:

    给你一颗有根树,树上每个节点都有其对应的颜色,有m次询问,每次问你以点v为父节点的子树内满足某种颜色的数量大于k的颜色一共有多少种

    题解:

    冷静分析,胡乱分析,询问次数这么多,但是并没有修改操作,倘若把询问离线下来就好了

    可是询问问的是每个点的树

    这个时候我们的dfs序就可以派上用场了

    dfs序:"所谓DFS序, 就是DFS整棵树依次访问到的结点组成的序列"

    "DFS序有一个很强的性质: 一颗子树的所有节点在DFS序内是连续的一段, 利用这个性质我们可以解决很多问题"

    通过对树进行一次dfs序操作,我们可以得到每个点他的子树所在的一段区间,这样我们就可以得到每个询问在dfs序下询问的区间了,那么我们怎么统计区间内颜色数量大于k的种类数量呢?

    由于我们得到了离线下来的询问区间,用莫队算法可以在O(nsqrt(n))的时间内得到所有询问的答案

    由于每次询问是查询区间内颜色种类的数量之和,我们需要用一个区间求和,单点修改的数据结构来维护莫队时统计答案和修改操作,因此我们可以用树状数组或者线段树来维护

    代码:

    /**
     *        ┏┓    ┏┓
     *        ┏┛┗━━━━━━━┛┗━━━┓
     *        ┃       ┃  
     *        ┃   ━    ┃
     *        ┃ >   < ┃
     *        ┃       ┃
     *        ┃... ⌒ ...  ┃
     *        ┃       ┃
     *        ┗━┓   ┏━┛
     *          ┃   ┃ Code is far away from bug with the animal protecting          
     *          ┃   ┃   神兽保佑,代码无bug
     *          ┃   ┃           
     *          ┃   ┃        
     *          ┃   ┃
     *          ┃   ┃           
     *          ┃   ┗━━━┓
     *          ┃       ┣┓
     *          ┃       ┏┛
     *          ┗┓┓┏━┳┓┏┛
     *           ┃┫┫ ┃┫┫
     *           ┗┻┛ ┗┻┛
     */
    // warm heart, wagging tail,and a smile just for you!
    //
    //                            _ooOoo_
    //                           o8888888o
    //                           88" . "88
    //                           (| -_- |)
    //                           O  =  /O
    //                        ____/`---'\____
    //                      .'  |     |//  `.
    //                     /  |||  :  |||//  
    //                    /  _||||| -:- |||||-  
    //                    |   | \  -  /// |   |
    //                    | \_|  ''---/''  |   |
    //                      .-\__  `-`  ___/-. /
    //                  ___`. .'  /--.--  `. . __
    //               ."" '<  `.___\_<|>_/___.'  >'"".
    //              | | :  `- \`.;` _ /`;.`/ - ` : | |
    //                 `-.   \_ __ /__ _/   .-` /  /
    //         ======`-.____`-.___\_____/___.-`____.-'======
    //                            `=---='
    //        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    //                     佛祖保佑      永无BUG
    #include <set>
    #include <map>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <ctime>
    #include <bitset>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    typedef pair<LL, LL> pLL;
    typedef pair<LL, int> pLi;
    typedef pair<int, LL> pil;;
    typedef pair<int, int> pii;
    typedef unsigned long long uLL;
    #define ls rt<<1
    #define rs rt<<1|1
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define bug printf("*********
    ")
    #define FIN freopen("input.txt","r",stdin);
    #define FON freopen("output.txt","w+",stdout);
    #define IO ios::sync_with_stdio(false),cin.tie(0)
    #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]
    "
    #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]
    "
    #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]
    "
    
    const double eps = 1e-8;
    const int mod = 1e9 + 7;
    const int maxn = 3e5 + 5;
    const int INF = 0x3f3f3f3f;
    const LL INFLL = 0x3f3f3f3f3f3f3f3f;
    struct EDGE {
        int v, nxt;
    } edge[maxn * 2];
    int head[maxn];
    int tot;
    void add_edge(int u, int v) {
        edge[tot].v = v;
        edge[tot].nxt = head[u];
        head[u] = tot++;
    }
    int n, m;
    int col[maxn];
    int dfn[maxn], st[maxn], ed[maxn], cnt;
    int vis[maxn];
    int num[maxn];
    int bit[maxn];
    int ans[maxn];
    void dfs(int u, int fa, int depth) {
        st[u] = ++cnt;
        num[cnt] = col[u];
        for(int i = head[u]; i != -1; i = edge[i].nxt) {
            int v = edge[i].v;
            if(v != fa) {
                dfs(v, u, depth + 1);
            }
        }
        ed[u] = cnt;
    }
    vector<int> vec[maxn];
    int v[maxn];
    int k[maxn];
    struct node {
        int l, r, id, k;
    } q[maxn];
    int pos[maxn];
    bool cmp(node a, node b) {
        if(pos[a.l] == pos[b.l]) return a.r < b.r;
        return pos[a.l] < pos[b.l];
    }
    int lowbit(int x) {
        return x & -x;
    }
    void update(int pos, int x) {
        if(pos <= 0) return;
        while(pos < maxn) {
            bit[pos] += x;
            pos += lowbit(pos);
        }
    }
    int query(int pos) {
        int ans = 0;
        while(pos) {
            ans += bit[pos];
            pos -= lowbit(pos);
        }
        return ans;
    }
    void add(int x) {
        update(vis[num[x]], -1);
        vis[num[x]]++;
        update(vis[num[x]], 1);
    }
    void del(int x) {
        update(vis[num[x]], -1);
        vis[num[x]]--;
        update(vis[num[x]], 1);
    }
    int main() {
    #ifndef ONLINE_JUDGE
        FIN
    #endif
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &col[i]);
        }
        memset(head, -1, sizeof(head));
        tot = cnt = 0;
        for(int i = 1, u, v; i <= n - 1; i++) {
            scanf("%d%d", &u, &v);
            add_edge(u, v);
            add_edge(v, u);
        }
        dfs(1, 0, 1);
        int sz = sqrt(cnt);
        for(int i = 1; i <= cnt; i++) {
            pos[i] = i / sz;
        }
        for(int i = 1; i <= m; i++) {
            scanf("%d%d", &v[i], &k[i]);
            q[i].l = st[v[i]];
            q[i].r = ed[v[i]];
            q[i].id = i;
            q[i].k = k[i];
        }
        sort(q + 1, q + m + 1, cmp);
        int L = 1, R = 0;
        for(int i = 1; i <= m; i++) {
            while(L < q[i].l) {
                L++;
                del(L - 1);
            }
            while(L > q[i].l) {
                add(L - 1);
                L--;
            }
            while(R < q[i].r) {
                R++;
                add(R);
            }
            while(R > q[i].r) {
                del(R);
                R--;
            }
            ans[q[i].id] = query(maxn - 1) - query(q[i].k - 1);
        }
        for(int i = 1; i <= m; i++) {
            printf("%d
    ", ans[i]);
        }
        return 0;
    }
    
    每一个不曾刷题的日子 都是对生命的辜负 从弱小到强大,需要一段时间的沉淀,就是现在了 ~buerdepepeqi
  • 相关阅读:
    圆上的整点
    学习笔记:用线性筛算不太常见的函数
    解题报告: luogu P1972
    解题报告: luogu P3907
    替罪羊树详解
    解题报告:luogu P2787
    解题报告:luogu P4170
    解题报告:luogu P4933
    10、.运维就是一场没有硝烟的战争
    九、模板层(三)
  • 原文地址:https://www.cnblogs.com/buerdepepeqi/p/10897505.html
Copyright © 2011-2022 走看看