[HNOI2016]网络 树链剖分,堆
生活随笔
收集整理的這篇文章主要介紹了
[HNOI2016]网络 树链剖分,堆
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
[HNOI2016]網(wǎng)絡(luò)
LG傳送門(mén)
表示亂搞比正解難想。
整體二分很好想吧。
但是為了好寫(xiě)快樂(lè),我們選擇三個(gè)\(\log\)的亂搞。
先樹(shù)剖,線段樹(shù)套堆維護(hù)區(qū)間最大值。對(duì)于一次修改,如果是插入,就把樹(shù)上除了這條鏈的地方加上這個(gè)重要度,如果是刪除則反之。注意線段樹(shù)可以標(biāo)記永久化,這里用的堆是一種(可能)叫懶惰堆的東西,直接看代碼都能理解。
//written by newbiechd #include <cstdio> #include <cctype> #include <vector> #include <queue> #include <algorithm> #define R register #define I inline #define B 1000000 using namespace std; const int N = 100003, M = 200003; char buf[B], *p1, *p2; I char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, B, stdin), p1 == p2) ? EOF : *p1++; } I int rd() {R int f = 0;R char c = gc();while (c < 48 || c > 57)c = gc();while (c > 47 && c < 58)f = f * 10 + (c ^ 48), c = gc();return f; } int s[N], fa[N], dep[N], siz[N], son[N], dfn[N], top[N], n, tim; struct road {int x, y;road() {}road(int x, int y) : x(x), y(y) {} }sta[N]; I int operator < (road a, road b) { return a.x ^ b.x ? a.x < b.x : a.y < b.y; } struct event {int x, y, z; }q[M]; struct prique {priority_queue <int> q1, q2;I void push(int x) { q1.push(x); }I void pop(int x) { q2.push(x); }I int top() {while (!q2.empty() && q1.top() == q2.top())q1.pop(), q2.pop();return q1.empty() ? -1 : q1.top();} }e[N << 2]; vector <int> g[N]; I int max(int x, int y) { return x > y ? x : y; } I void swap(int &x, int &y) { x ^= y, y ^= x, x ^= y; } void dfs1(int x, int f) {fa[x] = f, dep[x] = dep[f] + 1, siz[x] = 1;for (R int i = 0, y, m = 0; i < s[x]; ++i)if ((y = g[x][i]) ^ f) {dfs1(y, x), siz[x] += siz[y];if (siz[y] > m)m = siz[y], son[x] = y;} } void dfs2(int x, int t) {dfn[x] = ++tim, top[x] = t;if (son[x])dfs2(son[x], t);for (R int i = 0, y; i < s[x]; ++i)if (!dfn[y = g[x][i]])dfs2(y, y); } void modify(int k, int l, int r, int x, int y, int z, int opt) {if (x == l && y == r) {opt ? e[k].pop(z) : e[k].push(z);return ;}R int p = k << 1, q = p | 1, m = (l + r) >> 1;if (y <= m)modify(p, l, m, x, y, z, opt);elseif (m < x)modify(q, m + 1, r, x, y, z, opt);elsemodify(p, l, m, x, m, z, opt),modify(q, m + 1, r, m + 1, y, z, opt); } int query(int k, int l, int r, int x) {if (l == r)return e[k].top();R int p = k << 1, q = p | 1, m = (l + r) >> 1, o = e[k].top();if (x <= m)return max(o, query(p, l, m, x));elsereturn max(o, query(q, m + 1, r, x)); } I void insert(int x, int y, int z, int opt) {R int t = 0, i, l = 0;while (top[x] ^ top[y]) {if (dep[top[x]] < dep[top[y]])swap(x, y);sta[++t] = road(dfn[top[x]], dfn[x]), x = fa[top[x]];}if (dep[x] > dep[y])swap(x, y);sta[++t] = road(dfn[x], dfn[y]), sort(sta + 1, sta + t + 1);for (i = 1; i <= t; l = max(l, sta[i++].y))if (l + 1 < sta[i].x)modify(1, 1, n, l + 1, sta[i].x - 1, z, opt);if (l < n)modify(1, 1, n, l + 1, n, z, opt); } int main() {R int m, i, x, y, z, opt;n = rd(), m = rd();for (i = 1; i < n; ++i)x = rd(), y = rd(), g[x].push_back(y), g[y].push_back(x);for (i = 1; i <= n; ++i)s[i] = g[i].size();dfs1(1, 0), dfs2(1, 1);for (i = 1; i <= m; ++i) {opt = rd(), x = rd();if (opt == 0)y = rd(), z = rd(), q[i] = (event){x, y, z}, insert(x, y, z, opt);if (opt == 1)insert(q[x].x, q[x].y, q[x].z, opt);if (opt == 2)printf("%d\n", query(1, 1, n, dfn[x]));}return 0; }其實(shí)我覺(jué)得寫(xiě)正解的大佬們沒(méi)必要diss我們這種只會(huì)亂搞的小蒟蒻啊這個(gè)亂搞的思路也挺精巧的
轉(zhuǎn)載于:https://www.cnblogs.com/cj-chd/p/10453387.html
總結(jié)
以上是生活随笔為你收集整理的[HNOI2016]网络 树链剖分,堆的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 了解Linux操作系统发展阶段
- 下一篇: git撤销commit 并保存之前的修改