877F. Ann and Books (DFS sequence + Mo team + tree array)

Original address: https://codeforces.com/problemset/problem/375/D

Idea: given a tree with 111 as its root, each node in the tree has a color, and there are several colors in the subtree with vvv as its root, whose number of color occurrences is more than or equal to kkk

Idea: to find the subtree, we can use the order of dfsdfsdfs to transform the problem on the tree into the problem on the sequence. Then the problem is to find out how many colors in a certain interval [L,R][L,R][L,R] are greater than kkk
Because only inquiry, can use Mo team to optimize inquiry
As for the requirement of being greater than or equal to kkk, you can use tree array to query

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
int n, m, block;
int col[maxn], cnt[maxn * 10], ans[maxn];
int dfn, st[maxn], en[maxn];
//dfs
struct node {
    int u, v, nxt;
} e[2 * maxn];
int tot, head[maxn], val[maxn], l, r;
void init() {
    tot = 0;
    CLR(head, -1);
    dfn = 0;
}
void add_edge(int u, int v) {
    e[tot].v = v;
    e[tot].nxt = head[u];
    head[u] = tot++;
}

void dfs(int u, int fa) {
    st[u] = ++dfn;
    val[dfn] = col[u];
    for (int i = head[u]; ~i; i = e[i].nxt) {
        int v = e[i].v;
        if (v == fa) continue;
        dfs(v, u);
    }
    en[u] = dfn;
}
//Tree array
int bit[maxn];
int lowbit(int x) {
    return x & -x;
}
void add(int i, int x) {
    while (i <= n) {
        bit[i] += x;
        i += lowbit(i);
    }
}
int getsum(int i) {
    int sum = 0;
    while (i > 0) {
        sum += bit[i];
        i -= lowbit(i);
    }
    return sum;
}
//Mo team
struct query {
    int l, r, id, k;
    bool operator <(const query &a)const {
        if (l / block != a.l / block) return l / block < a.l / block;
        return r < a.r;
    }
} q[maxn];
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &col[i]);
    }
    init();
    block = sqrt(n);
    for (int i = 1; i <= n - 1; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        add_edge(u, v);
        add_edge(v, u);
    }
    dfs(1, -1);
    for (int i = 1; i <= m; i++) {
        int v, k;
        scanf("%d%d", &v, &k);
        q[i].id = i;
        q[i].l = st[v];
        q[i].r = en[v];
        q[i].k = k;
    }
    sort(q + 1, q + 1 + m);
    l = 1;
    r = 0;
    for (int i = 1; i <= m; i++) {
        while (r < q[i].r) {
            int color = val[++r];
            if (cnt[color] > 0) add(cnt[color], -1);
            cnt[color]++;
            add(cnt[color], 1);
        }
        while (r > q[i].r) {
            int color = val[r--];
            add(cnt[color], -1);
            cnt[color]--;
            if (cnt[color] > 0) add(cnt[color], 1);
        }
        while (l < q[i].l) {
            int color = val[l++];
            add(cnt[color], -1);
            cnt[color]--;
            if (cnt[color] > 0) add(cnt[color], 1);
        }
        while (l > q[i].l) {
            int color = val[--l];
            if (cnt[color] > 0) add(cnt[color], -1);
            cnt[color]++;
            add(cnt[color], 1);
        }
        int num = getsum(n) - getsum(q[i].k - 1);
        ans[q[i].id] = max(num, 0);
    }
    for (int i = 1; i <= m; i++) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

/*
2 1
1 2
1 2
1 1
*/


Posted on Sun, 10 Nov 2019 15:56:08 -0500 by jdashca