• Tree and Queries CodeForces


    http://codeforces.com/problemset/problem/375/D

    树莫队就是把树用dfs序变成线性的数组。 (原数组要根据dfs的顺序来变化)

    然后和莫队一样的区间询问。

    这题和普通莫队有点区别,他需要的不单单是统计区间元素种类个数,是区间元素种类个数 >= k[i]的个数。

    考虑最简单的用bit维护,复杂度多了个log

    观察到每次只需要 + 1  或者 -1

    用一个数组sum[k]表示种类数大于等于k的ans

    在numc[val]++之后,sum[numc[val]]++,表明这个种类出现次数是numc[val]次的贡献递增1

    在num[val]--之前,就需要把sum[numc[val]]--,表明贡献减1了

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 1e5 + 20;
    struct Edge {
        int u, v, tonext;
    }e[maxn * 2];
    int first[maxn], num;
    int c[maxn];
    void addEdge(int u, int v) {
        ++num;
        e[num].u = u, e[num].v = v, e[num].tonext = first[u];
        first[u] = num;
    }
    int L[maxn], R[maxn], dfs_clock;
    int color[maxn];
    void dfs(int cur, int fa) {
        L[cur] = ++dfs_clock;
        color[dfs_clock] = c[cur];
        for (int i = first[cur]; i; i = e[i].tonext) {
            int v = e[i].v;
            if (fa == v) continue;
            dfs(v, cur);
        }
        R[cur] = dfs_clock;
    }
    int magic;
    struct Node {
        int L, R, k, id;
        bool operator < (const struct Node & rhs) const {
            if (L / magic != rhs.L / magic) return L / magic < rhs.L / magic;
            else return R < rhs.R;
        }
    }query[maxn];
    int ans[maxn], numc[maxn];
    int bit[maxn];
    int lowbit(int x) {
        return x & (-x);
    }
    void add(int pos, int val) {
        while (pos) {
            bit[pos] += val;
            pos -= lowbit(pos);
        }
    }
    int ask(int pos) {
        int ans = 0;
        while (pos <= maxn - 20) {
            ans += bit[pos];
            pos += lowbit(pos);
        }
        return ans;
    }
    int suffix[maxn];
    void work() {
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; ++i) cin >> c[i];
        for (int i = 1; i <= n - 1; ++i) {
            int u, v;
            scanf("%d%d", &u, &v);
            addEdge(u, v);
            addEdge(v, u);
        }
        dfs(1, 0);
        magic = (int)sqrt(n + 0.5);
        for (int i = 1; i <= m; ++i) {
            int which, k;
            scanf("%d%d", &which, &k);
            query[i].L = L[which], query[i].R = R[which], query[i].k = k;
            query[i].id = i;
        }
        sort(query + 1, query + 1 + m);
        int L = 1, R = 0;
        int temp = 0;
        for (int i = 1; i <= m; ++i) {
            while (R < query[i].R) {
                ++R;
                suffix[++numc[color[R]]]++;
            }
            while (R > query[i].R) {
                suffix[numc[color[R]]--]--;
                --R;
            }
            while (L < query[i].L) {
                suffix[numc[color[L]]--]--;
                L++;
            }
            while (L > query[i].L) {
                L--;
                suffix[++numc[color[L]]]++;
            }
            ans[query[i].id] = suffix[query[i].k];
        }
        for (int i = 1; i <= m; ++i) {
            printf("%d
    ", ans[i]);
        }
    }
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
  • 相关阅读:
    关系型数据库vs非关系型数据库
    Vue使用日常记录
    【0805作业】模拟接力赛跑
    【0805作业】模拟叫号看病
    【0805作业】模拟多人爬山
    【0805作业】实现Runnable接口的方式创建线程
    【0805作业】继承Thread类创建线程,输出20次数字,“你好”,线程名
    超市会员管理系统
    【0802作业】循环注册十个账号,重启程序能正常登录
    【0802作业】复制图片
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7244411.html
Copyright © 2020-2023  润新知