http://acm.split.hdu.edu.cn/showproblem.php?pid=5029
题意:n个点的树,m次操作。每次操作输入L,R,V,表示在[L,R]这个区间加上V这个数字。比如[1,2]加上1,[1,3]加上1,那么1这个点就是{1,1},2也是{1,1},3是{1}。全部操作操作完之后,输出每个点中,最多的那个数字有几个。如果有相同的数字,就输出最小的那个数。比如{1,1,2,2},就输出1。
思路:树链剖分拍成链,然后通过找LCA,来离线预处理,然后最后通过离线暴力一遍线段树,来完成询问操作(md,add这个函数错了4个小时TAT)
//看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespace std; #pragma comment(linker,"/STACK:102400000,102400000") #define LL long long #define ALL(a) a.begin(), a.end() #define pb push_back #define mk make_pair #define fi first #define se second #define haha printf("haha ") const int maxn = 1e5 + 5; int belong[maxn], pos[maxn], son[maxn], id[maxn]; int par[maxn], sz[maxn], deep[maxn], ans[maxn]; int n, m, dfstime; vector<int> G[maxn]; vector<pair<int, int> > color[maxn]; int tree[maxn << 2]; void init(){ for (int i = 1; i <= n; i++) G[i].clear(); for (int i = 1; i <= 100000; i++) color[i].clear(); memset(belong, 0, sizeof(belong)); memset(son, 0, sizeof(son)); memset(par, 0, sizeof(par)); memset(deep, 0, sizeof(deep)); memset(sz, 0, sizeof(sz)); for (int i = 1; i < n; i++){ int u, v; scanf("%d%d", &u, &v); G[u].pb(v), G[v].pb(u); } } void dfs_size(int u, int fa, int road){ deep[u] = road, par[u] = fa; sz[u] = 1; for (int i = 0; i < G[u].size(); i++){ int v = G[u][i]; if (v == fa) continue; dfs_size(v, u, road + 1); sz[u] += sz[v]; if (sz[v] > sz[son[u]]) son[u] = v; } } void dfs_tree(int u, int fa, int chain){ pos[u] = ++dfstime; belong[u] = chain; id[dfstime] = u; if (son[u] == 0) return ; dfs_tree(son[u], u, chain); for (int i = 0; i < G[u].size(); i++){ int v = G[u][i]; if (v == fa || v == son[u]) continue; dfs_tree(v, u, v); } } void add(int x, int y, int c){///加入边 while (belong[x] != belong[y]){ if (deep[belong[x]] < deep[belong[y]]) swap(x, y); color[pos[belong[x]]].push_back(mk(c, 1)); color[pos[x] + 1].push_back(mk(c, -1)); x = par[belong[x]]; } if (deep[x] < deep[y]) swap(x, y); color[pos[y]].push_back(mk(c, 1)), color[pos[x] + 1].push_back(mk(c, -1)); } void update(int p, int l, int r, int o, int val){ if (p == l && p == r){ tree[o] += val; return ; } int mid = (l + r) / 2, lb = o << 1, rb = o << 1 | 1; if (p <= mid) update(p, l, mid, lb, val); if (p > mid) update(p, mid + 1, r, rb, val); tree[o] = max(tree[lb], tree[rb]); } int query(int l, int r, int o){ if (l == r) { if (tree[o] == 0) return 0; return l; } int mid = (l + r) / 2, lb = o << 1 , rb = o << 1 | 1; if (tree[lb] >= tree[rb]) return query(l, mid, lb); else return query(mid + 1, r, rb); } int main(){ while (scanf("%d%d", &n, &m) == 2){ if (n == 0 && m == 0) break; init(); dfstime = 0; dfs_size(1, 0, 1); dfs_tree(1, 0, 1); for (int i = 1; i <= m; i++){ int x, y, z; scanf("%d%d%d", &x, &y, &z); add(x, y, z); } memset(tree, 0, sizeof(tree)); for (int i = 1; i <= n; i++){ for (int j = 0; j < color[i].size(); j++){ int c = color[i][j].first, val = color[i][j].second; update(c, 1, 100000, 1, val); } ans[id[i]] = query(1, 100000, 1); } for (int i = 1; i <= n; i++){ printf("%d ", ans[i]); } } return 0; }