dsu on tree 题集 + ac代码

入门讲解

创作者博客
简要概述:其实就是分治吧,对与每个节点的子节点,我们先遍历它的轻儿子,把访问记录删去,然后再遍历它的重儿子,把访问记录留下,然后再去暴力遍历这个节点的轻儿子统计答案。
这样可以严格使复杂度的上限是 n log ⁡ ( n ) n\log(n) nlog(n)

600E - Lomsat gelral

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 1e5 + 10;

int head[N], to[N << 1], nex[N << 1], cnt = 1;

int n, col[N], sz[N], son[N];

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs(int rt, int fa) {
    sz[rt] = 1;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dfs(to[i], rt);
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
        sz[rt] += sz[to[i]];
    }
}

ll now_son, maxn, sum, num[N], ans[N];

void calc(int rt, int fa, int value) {
    num[col[rt]] += value;
    if(num[col[rt]] > maxn) {
        maxn = num[col[rt]];
        sum = col[rt];
    }
    else if(num[col[rt]] == maxn) sum += col[rt];
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == now_son) continue;
        calc(to[i], rt, value);
    }
}

void dsu(int rt, int fa, bool keep) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        dsu(to[i], rt, 0);
    }
    if(son[rt]) {
        dsu(son[rt], rt, 1);
        now_son = son[rt];
    }
    calc(rt, fa, 1);;
    now_son = 0;
    ans[rt] = sum;
    if(!keep) {
        calc(rt, fa, -1);
        maxn = sum = 0;
    }
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    n = read();
    for(int i = 1; i <= n; i++) col[i] = read();
    for(int i = 1; i < n; i++) {
        int x = read(), y = read();
        add(x, y);
        add(y, x);
    }
    dfs(1, 0);
    dsu(1, 0, 0);
    for(int i = 1; i <= n; i++) {
        printf("%lld%c", ans[i], i == n ? '\n' : ' ');
    }
	return 0;
}

树上数颜色

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 1e5 + 10;

int head[N], to[N << 1], nex[N << 1], cnt = 1;

int l[N], r[N], rk[N], col[N], son[N], sz[N], tot, n, m;

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs(int rt, int fa) {
    rk[++tot] = rt;
    l[rt] = tot;
    sz[rt] = 1;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dfs(to[i], rt);
        sz[rt] += sz[to[i]];
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
    }
    r[rt] = tot;
}

int ans[N], num[N], sum;

void dfs(int rt, int fa, bool keep) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        dfs(to[i], rt, 0);
    }
    if(son[rt]) dfs(son[rt], rt, 1);
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        for(int j = l[to[i]]; j <= r[to[i]]; j++) {
            if(!num[col[rk[j]]]++) sum++;
        }
    }
    if(!num[col[rt]]++) sum++;
    ans[rt] = sum;
    if(!keep) {
        sum = 0;
        for(int i = head[rt]; i; i = nex[i]) {
            if(to[i] == fa) continue;
            for(int j = l[to[i]]; j <= r[to[i]]; j++) {
                num[col[rk[j]]]--;
            }
        }
        num[col[rt]]--;
    }
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    n = read();
    for(int i = 1; i < n; i++) {
        int x = read(), y = read();
        add(x, y);
        add(y, x);
    }
    dfs(1, 0);
    for(int i = 1; i <= n; i++) col[i] = read();
    dfs(1, 0, 1);
    m = read();
    for(int i = 1; i <= m; i++) {
        int rt = read();
        printf("%d\n", ans[rt]);
    }
	return 0;
}

570D - Tree Requests

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 5e5 + 10;

int head[N], to[N], nex[N], cnt = 1;

char str[N];

int sz[N], dep[N], son[N], n, m, v[N], h[N];

struct Node {
    int h, id;
};

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs(int rt, int fa) {
    dep[rt] = dep[fa] + 1;
    sz[rt] = 1;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dfs(to[i], rt);
        sz[rt] += sz[to[i]];
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
    }
}

bitset<30> num[N];

int now_son, ans[N];

vector<Node> query[N];

void calc(int rt, int fa) {
    int now = str[rt] - 'a';
    if(num[dep[rt]][now]) num[dep[rt]][now] = 0;
    else num[dep[rt]][now] = 1;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == now_son) continue;
        calc(to[i], rt);
    }
}

void del(int rt, int fa) {
    int now = str[rt] - 'a';
    num[dep[rt]][now] = 0;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        del(to[i], rt);
    }
}

void dsu(int rt, int fa, bool keep) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        dsu(to[i], rt, 0);
    }
    if(son[rt]) {
        dsu(son[rt], rt, 1);
        now_son = son[rt];
    }
    calc(rt, fa);
    now_son = 0;
    for(auto i : query[rt]) {
        int h = i.h, id = i.id;
        ans[id] = num[h].count() <= 1;  
    }
    if(!keep) del(rt, fa);
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    scanf("%d %d", &n, &m);
    for(int i = 2; i <= n; i++) {
        int x; scanf("%d", &x);
        add(x, i);
    }
    scanf("%s", str + 1);
    dfs(1, 0);
    for(int i = 1; i <= m; i++) {
        int v, h;
        scanf("%d %d", &v, &h);
        query[v].pb({h, i});
    }
    dsu(1, 0, 1);
    for(int i = 1; i <= m; i++) {
        puts(ans[i] ? "Yes" : "No");
    }
	return 0;
}

阔力梯的树

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 1e5 + 10;

int head[N], to[N << 1], nex[N << 1], cnt = 1;

int sz[N], l[N], r[N], son[N], rk[N], n, tot, now_son;

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs(int rt, int fa) {
    rk[++tot] = rt;
    sz[rt] = 1, l[rt] = tot;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dfs(to[i], rt);
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
        sz[rt] += sz[to[i]];
    }
    r[rt] = tot;
}

set<int> st;

ll ans[N], sum;

void add(int x) {
    auto it = st.lower_bound(x);
    if(st.empty()) {
        st.insert(x);
        return;
    }
    if(it == st.end()) {
        --it;
        sum += 1ll * (x - *it) * (x - *it);
        st.insert(x);
        return;
    }
    if(it == st.begin()) {
        sum += 1ll * (*it - x) * (*it - x);
        st.insert(x);
        return;
    }
    int vr = *it, vl = *--it;
    sum += 1ll * (vr - x) * (vr - x) + 1ll * (x - vl) * (x - vl) - 1ll * (vr - vl) * (vr - vl);
    st.insert(x);
}

void dsu(int rt, int fa, bool keep) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        dsu(to[i], rt, 0);
    }
    if(son[rt]) {
        now_son = son[rt];
        dsu(son[rt], rt, 1);
    }
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        for(int j = l[to[i]]; j <= r[to[i]]; j++) {
            add(rk[j]);
        }
    }
    add(rt);
    ans[rt] = sum;
    if(!keep) {
        sum = 0;
        st.clear();
    }
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    n = read();
    for(int i = 2; i <= n; i++) {
        int x = read();
        add(x, i);
        add(i, x);
    }
    dfs(1, 0);
    dsu(1, 0, 1);
    for(int i = 1; i <= n; i++) {
        printf("%lld\n", ans[i]);
    }
	return 0;
} 

SGU - 507 Treediff

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 1e5 + 10;

int head[N], to[N << 1], nex[N << 1], cnt = 1;

int l[N], r[N], rk[N], col[N], son[N], sz[N], tot, n, m;

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs(int rt, int fa) {
    rk[++tot] = rt;
    l[rt] = tot;
    sz[rt] = 1;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dfs(to[i], rt);
        sz[rt] += sz[to[i]];
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
    }
    r[rt] = tot;
}

int ans[N], minn;

set<int> st;

void add(int x) {
    if(st.empty()) {
        st.insert(x);
        return ;
    }
    auto it = st.lower_bound(x);
    if(it == st.end()) {
        it--;
        minn = min(minn, x - *it);
    }
    else if(it == st.begin()) {
        minn = min(minn, *it - x);
    }
    else {
        int r = *it;
        it--;
        int l = *it;
        minn = min({minn, r - x, x - l});
    }
    st.insert(x);
}

void dfs(int rt, int fa, bool keep) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        dfs(to[i], rt, 0);
    }
    if(son[rt]) dfs(son[rt], rt, 1);
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        for(int j = l[to[i]]; j <= r[to[i]]; j++) {
            if(col[rk[j]] != 2147483647) add(col[rk[j]]);
        }
    }
    if(col[rt] != 2147483647) add(col[rt]);
    ans[rt] = minn;
    if(!keep)   st.clear(), minn = 2147483647;
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    n = read(), m = read();
    ans[1] = col[1] = 2147483647;
    for(int i = 2; i <= n; i++) {
        int x = read();
        add(x, i);
        ans[i] = col[i] = 2147483647;
    }
    for(int i = n - m + 1; i <= n; i++) {
        col[i] = read();
    }
    dfs(1, 0);
    minn = 2147483647;
    dfs(1, 0, 1);
    for(int i = 1; i <= n - m; i++) {
        printf("%d%c", ans[i], i == n - m ? '\n' : ' ');
    }
	return 0;
}

**HackerEarth, The Grass Type **

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 1e5 + 10;

int head[N], to[N << 1], nex[N << 1], cnt = 1;

int l[N], r[N], rk[N], col[N], son[N], sz[N], tot, n, m;
ll ans;

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs(int rt, int fa) {
    rk[++tot] = rt;
    l[rt] = tot;
    sz[rt] = 1;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dfs(to[i], rt);
        sz[rt] += sz[to[i]];
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
    }
    r[rt] = tot;
}

map<int, int> MP;

void dfs(int rt, int fa, bool keep) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        dfs(to[i], rt, 0);
    }
    if(son[rt]) dfs(son[rt], rt, 1);
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        for(int j = l[to[i]]; j <= r[to[i]]; j++) {
            if(col[rt] % col[rk[j]]) continue;
            ans += MP[col[rt] / col[rk[j]]];
        }
        for(int j = l[to[i]]; j <= r[to[i]]; j++) {
            MP[col[rk[j]]]++;
        }
    }
    ans += MP[1];
    MP[col[rt]]++;
    if(!keep) {
        MP[col[rt]]--;
        for(int i = head[rt]; i; i = nex[i]) {
            if(to[i] == fa) continue;
            for(int j = l[to[i]]; j <= r[to[i]]; j++) {
                MP[col[rk[j]]]--;
            }
        }
    }
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    n = read();
    for(int i = 1; i < n; i++) {
        int x = read(), y = read();
        add(x, y);
        add(y, x);
    }
    dfs(1, 0);
    for(int i = 1; i <= n; i++) col[i] = read();
    dfs(1, 0, 1);
    printf("%lld\n", ans);
	return 0;
}

E. Blood Cousins

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 1e5 + 10;

int head[N], to[N], nex[N], cnt = 1;

int sz[N], son[N], dep[N], fa[N][21], l[N], r[N], rk[N], tot, n, m;

bool root[N];

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs(int rt, int f) {
    l[rt] = ++tot;
    rk[tot] = rt;
    fa[rt][0] = f;
    dep[rt] = dep[f] + 1;
    sz[rt] = 1;
    for(int i = 1; (1 << i) <= dep[rt]; i++) {
        fa[rt][i] = fa[fa[rt][i - 1]][i - 1];
    }
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == f) continue;
        dfs(to[i], rt);
        sz[rt] += sz[to[i]];
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
    }
    r[rt] = tot;
}

int find(int x, int k) {
    int t = dep[x] - k;
    for(int i = 20; i >= 0; i--)
        if(dep[fa[x][i]] > t) x = fa[x][i];
    return fa[x][0];
}

int ans[N], num[N];

vector<pii> ask[N];

void dfs(int rt, int f, bool keep) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == f || to[i] == son[rt]) continue;
        dfs(to[i], rt, 0);
    }
    if(son[rt]) dfs(son[rt], rt, 1);
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == f || to[i] == son[rt]) continue;
        for(int j = l[to[i]]; j <= r[to[i]]; j++) {
            num[dep[rk[j]]]++;
        }
    }
    num[dep[rt]]++;
    for(auto i : ask[rt]) {
        int Dep = dep[rt] + i.first, id = i.second;
        ans[id] = num[Dep] - 1;
    }
    if(!keep) {
        num[dep[rt]]--;
        for(int i = head[rt]; i; i = nex[i]) {
            if(to[i] == f) continue;
            for(int j = l[to[i]]; j <= r[to[i]]; j++) {
                num[dep[rk[j]]]--;
            }
        }
    }
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    n = read();
    for(int i = 1; i <= n; i++) {
        int x = read();
        if(!x) {
            root[i] = true;
            continue;
        }
        add(x, i);
    }
    for(int i = 1; i <= n; i++) {
        if(root[i]) {
            dfs(i, 0);
        }
    }
    m = read();
    for(int i = 1; i <= m; i++) {
        int x = read(), y = read();
        int fa = find(x, y);
        if(fa == 0) {
            ans[i] = 0;
        }
        else {
            ask[fa].pb(mp(y, i));
        }
    }
    for(int i = 1; i <= n; i++) {
        if(root[i]) {
            dfs(i, 0, 0);
        }
    }
    for(int i = 1; i <= m; i++) {
        printf("%d%c", ans[i], i == m ? '\n' : ' ');
    }
	return 0;
}

E. Blood Cousins Return

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 2e5 + 10;

int head[N], to[N], nex[N], cnt = 1;

int sz[N], son[N], dep[N], l[N], r[N], rk[N], tot, n, m;

string col[N];

bool root[N];

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs(int rt, int fa) {
    sz[rt] = 1, dep[rt] = dep[fa] + 1;
    l[rt] = ++tot, rk[tot] = rt;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dfs(to[i], rt);
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
        sz[rt] += sz[to[i]];
    }
    r[rt] = tot;
}

set<string> st[N];

vector<pii> ask[N];

int ans[N];

void dfs(int rt, int fa, bool keep) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        dfs(to[i], rt, 0);
    }
    if(son[rt]) dfs(son[rt], rt, 1);
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        for(int j = l[to[i]]; j <= r[to[i]]; j++) {
            st[dep[rk[j]]].insert(col[rk[j]]);
        }
    }
    st[dep[rt]].insert(col[rt]);
    for(auto i : ask[rt]) {
        int Dep = dep[rt] + i.first, id = i.second;
        ans[id] = st[Dep].size();
    }
    if(!keep) {
        for(int i = head[rt]; i; i = nex[i]) {
            if(to[i] == fa) continue;
            for(int j = l[to[i]]; j <= r[to[i]]; j++) {
                st[dep[rk[j]]].erase(col[rk[j]]);
            }
        }
        st[dep[rt]].erase(col[rt]);
    }
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n;
    for(int i = 1; i <= n; i++) {
        cin >> col[i];
        int x; cin >> x;
        if(!x) root[i] = true;
        else {
            add(x, i);
        }
    }
    for(int i = 1; i <= n; i++) {
        if(root[i]) dfs(i, 0);
    }
    cin >> m;
    for(int i = 1; i <= m; i++) {
        int x, y;
        cin >> x >> y;
        ask[x].pb(mp(y, i));
    }
    for(int i = 1; i <= n; i++) {
        if(root[i]) dfs(i, 0, 0);
    }
    for(int i = 1; i <= m; i++) {
        cout << ans[i] << endl;
    }
	return 0;
}

F. Dominant Indices

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 1e6 + 10;

int head[N], to[N << 1], nex[N << 1], cnt = 1;

int sz[N], dep[N], son[N], l[N], r[N], rk[N], tot, n;

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs(int rt, int fa) {
    sz[rt] = 1, l[rt] = ++tot;
    rk[tot] = rt, dep[rt] = dep[fa] + 1;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dfs(to[i], rt);
        sz[rt] += sz[to[i]];
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
    }
    r[rt] = tot;
}

int ans[N], num[N], now_ans, maxn;

void dfs(int rt, int fa, bool keep) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        dfs(to[i], rt, 0);
    }
    if(son[rt]) dfs(son[rt], rt, 1);
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        for(int j = l[to[i]]; j <= r[to[i]]; j++) {
            int Dep = dep[rk[j]];
            num[Dep]++;
            if(num[Dep] > maxn) {
                maxn = num[Dep];
                now_ans = Dep;
            }
            else if(num[Dep] == maxn && Dep < now_ans) now_ans = Dep;
        }
    }
    int Dep = dep[rt];
    num[Dep]++;
    if(num[Dep] > maxn) {
        maxn = num[Dep];
        now_ans = Dep;
    }
    else if(num[Dep] == maxn && Dep < now_ans) now_ans = Dep;
    ans[rt] = now_ans - Dep;
    if(!keep) {
        for(int i = l[rt]; i <= r[rt]; i++) {
            int Dep = dep[rk[i]];
            num[Dep]--;
        }
        now_ans = maxn = 0;
    }
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    n = read();
    for(int i = 1; i < n; i++) {
        int x = read(), y = read();
        add(x, y);
        add(y, x);
    }
    dfs(1, 0);
    dfs(1, 0, 1);
    for(int i = 1; i <= n; i++) {
        printf("%d\n", ans[i]);
    }
	return 0;
}

D. Water Tree

据说能 d s u   o n   t r e e dsu\ on\ tree dsu on tree,因为看到树链剖分好些就用树链剖分实现了。

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 5e5 + 10;

int head[N], to[N << 1], nex[N << 1], cnt = 1, n, m;

int sz[N], son[N], fa[N], dep[N], rk[N], id[N], top[N], l[N], r[N], tot;

int tree[N << 2], lazy[N << 2];

void dfs1(int rt, int f) {
    sz[rt] = 1, fa[rt] = f;
    dep[rt] = dep[f] + 1;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == f) continue;
        dfs1(to[i], rt);
        sz[rt] += sz[to[i]];
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
    }
}

void dfs2(int rt, int tp) {
    id[rt] = l[rt] = ++tot;
    top[rt] = tp, rk[tot] = rt;
    if(!son[rt]) {
        r[rt] = tot;
        return ;
    }
    dfs2(son[rt], tp);
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa[rt] || to[i] == son[rt]) continue;
        dfs2(to[i], to[i]);
    }
    r[rt] = tot;
}

void push_down(int rt) {
    if(lazy[rt] != -1) {
        lazy[ls] = lazy[rs] = lazy[rt];
        tree[ls] = tree[rs] = lazy[rt];
        lazy[rt] = -1;
    }
}

void update(int rt, int l, int r, int L, int R, int value) {
    if(l >= L && r <= R) {
        lazy[rt] = value;
        tree[rt] = value;
        return ;
    }
    push_down(rt);
    if(L <= mid) update(lson, L, R, value);
    if(R > mid)  update(rson, L, R, value);
}

int query(int rt, int l, int r, int L, int R) {
    if(l == r) {
        return tree[rt];
    }
    push_down(rt);
    if(L <= mid) return query(lson, L, R);
    return query(rson, L, R);
}

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void change(int x, int y) {
    while(top[x] != top[y]) {
        if(dep[top[x]] < dep[top[y]]) swap(x, y);
        update(1, 1, n, id[top[x]], id[x], 0);
        x = fa[top[x]];
    }
    if(dep[x] > dep[y]) swap(x, y);
    update(1, 1, n, id[x], id[y], 0);
}

void print(int rt, int l, int r) {
    if(l == r) {
        printf("%d ", tree[rt]);
        return ;
    }
    push_down(rt);
    print(lson);
    print(rson);
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    memset(lazy, -1, sizeof lazy);
    n = read();
    for(int i = 1; i < n; i++) {
        int x = read(), y = read();
        add(x, y);
        add(y, x);
    }
    dfs1(1, 0);
    dfs2(1, 1);
    m = read();
    for(int i = 1; i <= m; i++) {
        int op = read(), u = read();
        if(op == 1) {
            update(1, 1, n, l[u], r[u], 1);
        }
        else if(op == 2) {
            change(1, u);
        }
        else {
            printf("%d\n", query(1, 1, n, id[u], id[u]));
        }
    }
	return 0;
}

D. Tree and Queries

这道题目之前是用莫队写过,这次用 d s u   o n   t r e e dsu\ on\ tree dsu on tree重新写了一遍。

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

const int N = 2e5 + 10;

int head[N], to[N << 1], nex[N << 1], cnt = 1;

int sz[N], son[N], col[N], l[N], r[N], rk[N], tot, n, m;

void add(int x, int y) {
    to[cnt] = y;
    nex[cnt] = head[x];
    head[x] = cnt++;
}

void dfs(int rt, int fa) {
    sz[rt] = 1, l[rt] = ++tot, rk[tot] = rt;
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa) continue;
        dfs(to[i], rt);
        sz[rt] += sz[to[i]];
        if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i];
    }
    r[rt] = tot;
}

int ans[N], num[N], sum[N];

vector<pii> ask[N];

void add(int x) {
    sum[++num[x]]++;
}

void del(int x) {
    sum[num[x]--]--;
}

void dfs(int rt, int fa, bool keep) {
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        dfs(to[i], rt, 0);
    }
    if(son[rt]) dfs(son[rt], rt, 1);
    for(int i = head[rt]; i; i = nex[i]) {
        if(to[i] == fa || to[i] == son[rt]) continue;
        for(int j = l[to[i]]; j <= r[to[i]]; j++) {
            add(col[rk[j]]);
        }
    }
    add(col[rt]);
    for(auto i : ask[rt]) {
        int minn = i.first, id = i.second;
        ans[id] = sum[minn];
    }
    if(!keep) {
        for(int j = l[rt]; j <= r[rt]; j++) {
            del(col[rk[j]]);
        }
    }
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    n = read(), m = read();
    for(int i = 1; i <= n; i++) col[i] = read();
    for(int i = 1; i < n; i++) {
        int x = read(), y = read();
        add(x, y);
        add(y, x);
    }
    dfs(1, 0);
    for(int i = 1; i <= m; i++) {
        int x = read(), y = read();
        ask[x].pb(mp(y, i));
    }
    dfs(1, 0, 1);
    for(int i = 1; i <= m; i++) {
        printf("%d\n", ans[i]);
    }
	return 0;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值