bzoj4538: [HNOI2016]网络
来源:互联网 发布:淘宝运费险是自动退吗 编辑:程序博客网 时间:2024/06/04 19:32
题目链接
维护一颗树。在每个时刻,有以下三个操作。
(u,v,w) : 向从u 至v 的路径上添加一个重要度为w 的任务。(t) : 取消t 时刻添加的任务。(x) 查询所有未覆盖x 节点的任务中重要度的最大值。
这道题有诸多做法,然而我直接当做树链剖分练习题来做了。
对于这样的三个操作,我们可以考虑用树剖来维护。查询不覆盖某节点的任务难以直接用线段树实现,我们可以反其道而行之,将操作
这题还可以用kdtree,点分治,二分+树链交等各种优雅的做法秒杀,然而我一个都不会。
#include <queue>#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;struct event { int val, id; inline bool operator < (const event &rhs) const { return val < rhs.val; }}tmpe;typedef priority_queue<event> heap;const int N = 100010;int n, m;vector<int> E[N];int size[N], dep[N], fa[N], son[N], top[N], seg[N], segCnt;void dfs1(int u, int f) { size[u] = 1; dep[u] = dep[fa[u] = f] + 1; for (int i = 0; i < E[u].size(); i++) { int &v = E[u][i]; if (v == f) continue; dfs1(v, u); size[u] += size[v]; if (size[v] > size[son[u]]) son[u] = v; }}void dfs2(int u, int tp) { top[u] = tp; seg[u] = ++segCnt; if (! son[u]) return; dfs2(son[u], tp); for (int i = 0; i < E[u].size(); i++) { int &v = E[u][i]; if (v == fa[u] || v == son[u]) continue; dfs2(v, v); }}inline void initTree() { dfs1(1, 0); dfs2(1, 1);}bool disable[N<<1];heap hp[N<<1];#define g(l, r) (l + r | l != r)#define o g(l, r)#define ls g(l, mid)#define rs g(mid + 1, r)int gl, gr, gans;#define cg(l, r) gl = l; \ gr = r#define H hp[o]void ins(int l, int r) { if (gl > gr) return; if (gl <= l && r <= gr) { H.push(tmpe); return; } int mid = l + r >> 1; if (gl <= mid) ins(l, mid); if (mid + 1 <= gr) ins(mid + 1, r);}void query(int l, int r) { while (! H.empty() && disable[H.top().id]) H.pop(); if (! H.empty()) gans = max(gans, H.top().val); if (l == r) return; int mid = l + r >> 1; if (gl <= mid) query(l, mid); else query(mid + 1, r);}event cf[110<<1];inline void Insert(int u, int v) { int ecnt = 0; int f1 = top[u], f2 = top[v]; while (f1 != f2) { if (dep[f1] < dep[f2]) { swap(f1, f2); swap(u, v); } cf[++ecnt] = (event){seg[f1], 1}; cf[++ecnt] = (event){seg[u] + 1, -1}; u = fa[f1], f1 = top[u]; } if (dep[u] < dep[v]) swap(u, v); cf[++ecnt] = (event){seg[v], 1}; cf[++ecnt] = (event){seg[u] + 1, -1}; //O(logNlog(logN))差分求补集 sort(cf + 1, cf + 1 + ecnt); int sum = 0, left = 1; for (int i = 1; i <= ecnt; i++) { if (sum == 0) { cg(left, cf[i].val - 1); ins(1, n); sum += cf[i].id; } else { sum += cf[i].id; if (sum == 0) left = cf[i].val; } } cg(left, n); ins(1, n);}inline void Query(int u) { gans = -1; cg(seg[u], seg[u]); query(1, n); printf("%d\n", gans);}inline void work() { for (int id = 1; id <= m; id++) { int type; scanf("%d", &type); if (type == 0) { int a, b, v; scanf("%d%d%d", &a, &b, &v); tmpe = (event){v, id}; Insert(a, b); } if (type == 1) { int t; scanf("%d", &t); disable[t] = true; } if (type == 2) { int x; scanf("%d", &x); Query(x); } }}int main() { cin >> n >> m; for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); E[u].push_back(v); E[v].push_back(u); } initTree(); work(); return 0;}
1 0
- BZOJ4538: [Hnoi2016]网络
- BZOJ4538 HNOI2016 网络
- bzoj4538: [Hnoi2016]网络
- bzoj4538: [Hnoi2016]网络
- [bzoj4538][Hnoi2016]网络
- bzoj4538【HNOI2016】网络
- bzoj4538: [HNOI2016]网络
- bzoj4538: [Hnoi2016]网络
- 【BZOJ4538】【HNOI2016】网络
- Bzoj4538:[Hnoi2016]网络:整体二分+树状数组
- 【bzoj4538】【HNOI2016】【网络】【树链剖分+线段树套堆】
- [BZOJ4538]网络
- BZOJ4538:[Hnoi2016]网络 (整体二分+Lca+树状数组/线段树+路径交/树链剖分+Heap)
- BZOJ4538 网络 [树链剖分]
- HNOI2016 网络
- HNOI2016 网络
- [HNOI2016] 网络
- BZOJ 4538: [Hnoi2016]网络
- javascript--函数总结
- 关于open操作的O_EXCL的存在应用价值理解
- [leetcode]Tow Sum(java)
- hdu5894组合数学
- hdu1495 非常可乐(规律)
- bzoj4538: [HNOI2016]网络
- c++ 函数
- 类,面和对象
- light oj 1005 - Rooks (组合数学)
- 优秀程序员的本质
- vijos1037-搭建双塔
- 发射器选址
- 《Effect C++》学习------条款21:当必须返回对象时,别妄想返回其reference
- python的高级特性