MnZn刚学OI,求调树上莫队
查看原帖
MnZn刚学OI,求调树上莫队
333119
__Seniorious__楼主2023/10/13 08:59

RT,由于是自己乱胡的,为了处理链上情况口胡了一个欧拉括号序状物,就是欧拉序在出这个点时再记录一次,实测应该是对的,过掉了模拟赛的题。代码如下:

/**
 * @author : cyb1010
 * @date   : 2023-10-12 09:00:43
 * @file   : square.cpp
 */
#include <bits/stdc++.h>
using namespace std;
#define fo(s) freopen(s ".in", "r", stdin), freopen(s ".out", "w", stdout)
#define fi first
#define se second
typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
unordered_map<int, int> M;
int __, n, q, a[50010], buc[200010], cnt, ans[100010], cc;
vector<int> g[50010];
int out[50010], id[150010], idx, used[50010], tot[50010];
void init(int p, int fa) {
    id[++idx] = p, tot[p] = 2;
    for (auto i : g[p])
        if (i != fa) init(i, p), id[++idx] = p, tot[p]++;
    id[++idx] = p, out[p] = idx;
}
void ins_val(int x) { (buc[x]++ == 0) && ++cnt; }
void del_val(int x) { (--buc[x] == 0) && --cnt; }
void ins(int p) {
    if (!used[p]++) ins_val(a[p]);
    if (used[p] == tot[p]) del_val(a[p]);
}
void del(int p) {
    if (used[p] == tot[p]) ins_val(a[p]);
    if (!--used[p]) del_val(a[p]);
}
int bel[150010], blo = 400;
struct qry {
    int l, r, id;
    qry() {}
    qry(int _l, int _r, int _id) : l(_l), r(_r), id(_id) {}
} op[100010];
bool cmp(qry x, qry y) {
    if (bel[x.l] == bel[y.l]) return (bel[x.l] & 1) ? x.r < y.r : x.r > y.r;
    return x.l < y.l;
}
int f(int x) { return M.find(x) == M.end() ? M[x] = ++cc : M[x]; }
int main() {
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]), a[i] = f(a[i]);
    for (int i = 1, x, y; i < n; i++)
        scanf("%d%d", &x, &y), g[x].push_back(y), g[y].push_back(x);
    init(1, 0);
    for (int i = 1; i <= idx; i++) bel[i] = (i - 1) / blo + 1;
    for (int i = 1, x, y; i <= q; i++)
        scanf("%d%d", &x, &y),
            op[i] = qry(min(out[x], out[y]), max(out[x], out[y]) - 1, i);
    sort(op + 1, op + 1 + q, cmp);
    for (int i = 1, l = 1, r = 0; i <= q; i++) {
        while (r < op[i].r) ins(id[++r]);
        while (l > op[i].l) ins(id[--l]);
        while (l < op[i].l) del(id[l++]);
        while (r > op[i].r) del(id[r--]);
        ans[op[i].id] = cnt;
    }
    for (int i = 1; i <= q; i++) printf("%d\n", ans[i]);
    return 0 ^ __ ^ 0;
}
2023/10/13 08:59
加载中...