HDU 5029Relief grain(树链剖分+线段树)
来源:互联网 发布:竞价软件哪个好 编辑:程序博客网 时间:2024/05/16 06:54
题意:给你一颗n个节点的树,现在执行m次操作,每次操作[a, b, k]表示a到b的路径上的所有点都加上一个颜色k。
m次操作之后输出每个点的出现次数最多的那个颜色(若有多个颜色输出值最小的)。n, m, k <= 1e5
思路:我们可以先把他想成在区间上执行操作,这样题意就变成了:
一个区间[1, n],m次操作[a, b, k],表示a-b区间每个节点添加一个颜色k,mci曹组后输出n个数,表示每个点的出现
的颜色次数最多的那个颜色(若有多个,输出颜色最小的).
因为是所有操作执行完成后再输出,所以我们可以进行离线操作。对于每个操作a,b,k,我们将a节点上标记一个k,b+1节点上标记一个-k,因为每个点可能有多个标记所以我们可以用vector来存,先将所有的操作都打到这个线性的结
构上,再用线段树来离线维护。线段树区间维护的是它的区间最后出现最多的颜色和这个颜色出现的次数,这样的话
我们可将标记从小到大排序,扫到每个节点都将他所存储的标号更新到线段树上,如果标记
是正值就将对应的颜色的次数+1,否则-1,将所有这个点的标记都传完后,取根节点的值就是被染次数最多的颜色和
次数,也就知道了这个点的答案,因为影响这个点的标记已经全部处理完了。
至于这题是树上,而不是区间,我们可以进行树剖,这样每次操作[a, b]只不过是变成多个区间而已,和上述一样处理
就行。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;const int maxn = 1e5+5;const int INF = 0x3f3f3f3f;int deep[maxn], fa[maxn], top[maxn], tree[maxn], pre[maxn], son[maxn], num[maxn];int n, m, tot, k, head[maxn], ans[maxn];int treeNum[maxn*4], treeKey[maxn*4];struct node{ int u, v, next;}edge[maxn*2];struct qnode{ int l, r, k; qnode(){} qnode(int ll, int rr, int kk):l(ll), r(rr), k(kk) {}};vector<qnode> op;vector<int> a[maxn];void init(){ k = tot = 0; memset(head, -1, sizeof(head)); memset(son, 0, sizeof(son)); memset(num, 0, sizeof(num)); op.clear(); for(int i = 0; i < maxn; i++) a[i].clear();}void addEdge(int u, int v){ edge[k].v = v; edge[k].next = head[u]; head[u] = k++;}void dfs1(int u, int pre, int d){ fa[u] = pre; deep[u] = d; num[u] = 1; for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].v; if(v == pre) continue; dfs1(v, u, d+1); num[u] += num[v]; if(!son[u] || num[v] > num[son[u]]) son[u] = v; }}void dfs2(int u, int tp){ tree[u] = ++tot; pre[tree[u]] = u; top[u] = tp; if(!son[u]) return ; dfs2(son[u], tp); for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].v; if(v != fa[u] && v != son[u]) dfs2(v, v); }}void change(int x, int y, int z){ int f1 = top[x], f2 = top[y]; while(f1 != f2) { if(deep[f1] < deep[f2]) swap(f1, f2), swap(x, y); op.push_back(qnode(tree[f1], tree[x], z)); x = fa[f1]; f1 = top[x]; } if(deep[x] > deep[y]) swap(x, y); op.push_back(qnode(tree[x], tree[y], z));}void pushup(int root){ if(treeNum[root*2+1] > treeNum[root*2]) treeKey[root] = treeKey[root*2+1]; else treeKey[root] = treeKey[root*2]; treeNum[root] = max(treeNum[root*2], treeNum[root*2+1]);}void build(int root, int l, int r){ treeNum[root] = 0; if(l == r) { treeKey[root] = l; return ; } int mid = (l+r)/2; build(root*2, l, mid); build(root*2+1, mid+1, r); pushup(root);}void update(int root, int l, int r, int pos, int val){ if(l == r) { treeNum[root] += val; return ; } int mid = (l+r)/2; if(pos <= mid) update(root*2, l, mid, pos, val); else update(root*2+1, mid+1, r, pos, val); pushup(root);}int main(void){ while(cin >> n >> m) { init(); if(!n && !m) break; for(int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); addEdge(u, v); addEdge(v, u); } dfs1(1, 0, 1); dfs2(1, 1); int maxz = 1; for(int i = 1; i <= m; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); change(x, y, z); maxz = max(maxz, z); } int len = op.size(); for(int i = 0; i < len; i++) { int l = op[i].l; int r = op[i].r; int K = op[i].k; a[l].push_back(K); a[r+1].push_back(-K); } for(int i = 1; i <= n; i++) sort(a[i].begin(), a[i].end()); build(1, 1, maxz); for(int i = 1; i <= n; i++) { int len = a[i].size(); for(int j = 0; j < len; j++) { int tmp = a[i][j]; if(tmp < 0) update(1, 1, maxz, -tmp, -1); else update(1, 1, maxz, tmp, 1); } ans[pre[i]] = treeKey[1]; if(treeNum[1] == 0) ans[pre[i]] = 0; } for(int i = 1; i <= n; i++) printf("%d\n", ans[i]); } return 0;}
阅读全文
1 0
- hdu 5029 Relief grain (树链剖分+线段树)
- hdu 5029 Relief grain(树链剖分+线段树)
- HDU 5029Relief grain(树链剖分+线段树)
- HDU 5029 Relief grain 树链剖分+线段树离线维护
- HDU 5029 Relief grain 树链剖分 离线 线段树
- HDU 5029 Relief grain (树链剖分 + 线段树)
- [HDU 5029] Relief grain (树链剖分+线段树)
- HDU 5029 Relief grain(恶心的树链剖分 + 线段树)
- HDU 5029Relief grain-树链剖分+线段树+离线
- hdu 5029 Relief grain 树链剖分
- hdu 5029 Relief grain 树链剖分
- HDU 5209 Relief grain 解题报告(树链剖分 + 线段树)
- HDU 5029 Relief grain
- hdu 5029 Relief grain
- HDU5029 Relief grain(树链剖分+线段树)
- Hdu 5029 Relief grain(树链剖分)
- HDU 5029 Relief grain(树链剖分)
- HDU 5029 Relief grain --树链剖分第一题
- bzoj2330 [SCOI2011]糖果(差分约束+spfa)
- 【HDU 3966 】Aragorn's Story 【树链剖分 基于点权,查询单点值,修改路径上的点权】
- cs231n作业配置
- 嵌入式多路温湿度监控系统(八网络客户端程序)
- HTML5教程之details展开收缩标签的应用
- HDU 5029Relief grain(树链剖分+线段树)
- 设计模式之Builder模式的简单实现
- sizeof使用规则及陷阱分析
- 数据结构——第三讲、树(上)(3)
- 常用的svn和git命令
- 自考之数据结构思维导图
- javaBean验证框架(4)—自定义约束
- opencv中加入contrib模块
- Nginx配置文件详解