Tree heuristic merge "data structure"

dsu on tree used to solve the tree problem. Can \ (O (nlgon) \) completed static sub-tree statistics. However, it can not be modified, only the sub-tree statistics, not statistically chain.

Let's look at a problem. There is a tree, each point has a weight. The value of seeking the tree of every sub-tree of all the weights and, if there are multiple modes that have statistics. Consider \ (O (n ^ 2) \) violence, for each sub-tree, the tree through all the points of the sub-tree, with a barrel record number of times each number appears, and statistics about the number of the public, then empty the bucket Eliminate the effects of. Here is the code.

void add(int x, int fa, int val) {
    cnt[col[x]] += val;
    if(cnt[col[x]] > mx) mx = cnt[col[x]], sum = col[x];
    else if(cnt[col[x]] == mx) sum += col[x];
    for(int i = 0; i < G[x].size(); i++) {
        int y = G[x][i];
        if (y != fa) add(y, x, val);
    }
}
void dfs(int x, int fa) {
    for(int i = 0; i < G[x].size(); i++) {
        int y = G[x][i];
        if(y != fa) dfs(y, x);
    }
    add(x, fa, 1); ans[x] = sum;
    add(x, fa, -1), sum = 0, mx = 0;
}

Can be found in a search to the last son is not necessary to eliminate the effect of eliminating the influence of heavy occupancy time of the sons of sons. It can be added to optimize a son does not eliminate the effects of weight in the violence. This is the core idea of ​​dsu on tree, dsu on the process tree follows, there is order.

  1. Through each node
  2. Recursive solve all the sons of light, while eliminating the impact generated recursively
  3. Recursive son, does not eliminate the influence of recursion
  4. Statistics violence affects all sons of light answers
  5. Updates node of the answer
  6. Delete violence affects all sons of light answers

Plus an optimized only eliminate the effects of heavy son. Others are violent, as if still \ (O (n) \) , and it is not. Because a number of the node to the root of the heavy chain and light chain path does not exceed \ (logN \) item, only the light dfs edge, will be merged into a subtree son of a light heavy chain, then each point up to merge up \ (logn \) times, and overall complexity \ (O (nlogn) \) .

Learned dsu on the tree, we can handle the above problems, it was CodeForeces600E Lomsat gelral.

#include <bits/stdc++.h>
using namespace std;
#define re register
#define F first
#define S second
#define mp make_pair
#define lson (p << 1)
#define rson (p << 1 | 1)
typedef long long ll;
typedef pair<int, int> P;
const int N = 5e5 + 5, M = 5e5 + 5;
const int INF = 0x3f3f3f3f;
inline int read() {
    int X = 0,w = 0; char ch = 0;
    while(!isdigit(ch)) {w |= ch == '-';ch = getchar();}
    while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48),ch = getchar();
    return w ? -X : X;
}
inline void write(int x){
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}
int n, val[N], cnt[N], mx;
ll sum, ans[N];
struct edge{
    int to, nxt;
}e[M];
int head[N], tot;
void addedge(int x, int y){
    e[++tot].to = y, e[tot].nxt = head[x], head[x] = tot;
}
int sz[N], son[N];
void dfs1(int x, int fa){
    sz[x] = 1;
    for (int i = head[x]; i; i = e[i].nxt){
        int y = e[i].to;
        if (y != fa){
            dfs1(y, x); sz[x] += sz[y];
            if (sz[y] > sz[son[x]]) son[x] = y;
        }
    }
}
bool vis[N];
void add(int x, int fa, int k){
    cnt[val[x]] += k;
    if (k > 0 && cnt[val[x]] > mx) sum = val[x], mx = cnt[val[x]];
    else if (k > 0 && cnt[val[x]] == mx) sum += val[x];
    for (int i = head[x]; i; i = e[i].nxt){
        int y = e[i].to;
        if (y != fa && !vis[y]) add(y, x, k);
    }
}
void dfs2(int x, int fa, int flg){
    for (int i = head[x]; i; i = e[i].nxt){
        int y = e[i].to;
        if (y != fa && y != son[x]) dfs2(y, x, 0);
    }
    if (son[x]) dfs2(son[x], x, 1), vis[son[x]] = 1;
    add(x, fa, 1); ans[x] = sum;
    if (son[x]) vis[son[x]] = 0; 
    if (!flg) add(x, fa, -1), sum = mx = 0;
}
int main() {
    n = read();
    for (int i = 1; i <= n; i++) val[i] = read();
    for (int i = 1; i < n; i++){
        int x = read(), y = read();
        addedge(x, y); addedge(y, x);
    }
    dfs1(1, 0); dfs2(1, 0, 0);
    for (int i = 1; i <= n; i++) printf("%lld ", ans[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/lyfoi/p/11621976.html