日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P3250 [HNOI2016]网络(利用堆建线段树 + 树剖)

發布時間:2023/12/4 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P3250 [HNOI2016]网络(利用堆建线段树 + 树剖) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

P3250 [HNOI2016]網絡

做法有點神奇!!!利用堆作為節點建立一顆線段樹,用堆維護線段樹上點的信息。

說說查詢操作,我們的目的是要查詢,沒有經過這個點的事件最大值,考慮如何維護。

我們定義線段樹上的信息,每個點記錄的是沒有經過這個區間的事件值。

事件插入,我們可以利用樹剖得到從x?>yx->yx?>y的路徑形成的log?n\log nlogn個連續的段,

我們先把這些段給存下來,然后再按照lll排個序,在這些段之外插入事件值。

同樣的事件刪除,我們只要在這些段之外刪除事件值即可,這里好像有(log?n)3(\log n) ^ 3(logn)3

對于查詢操作,我們只要去查找這個點所在的區間的最大值即可(因為我們記錄的是不在這個區間里的值)。

#include <bits/stdc++.h> #define mid (l + r >> 1) #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r #define ls rt << 1 #define rs rt << 1 | 1using namespace std;const int N = 1e5 + 10;struct Heap {priority_queue<int> a, b;void push(int x) {a.push(x);}void erase(int x) {b.push(x);}int top() {while (b.size() && a.top() == b.top()) {a.pop(), b.pop();}return a.top();} }tree[N << 2];void build(int rt, int l, int r) {tree[rt].push(-1);if (l == r) {return ;}build(lson);build(rson); }void update(int rt, int l, int r, int L, int R, int value, int op) {if (l >= L && r <= R) {if (op) {tree[rt].push(value);}else {tree[rt].erase(value);}return ;}if (L <= mid) {update(lson, L, R, value, op);}if (R > mid) {update(rson, L, R, value, op);} }int query(int rt, int l, int r, int L, int R) {if (l >= L && r <= R) {return tree[rt].top();}int ans = tree[rt].top();if (L <= mid) {ans = max(ans, query(lson, L, R));}if (R > mid) {ans = max(ans, query(rson, L, R));}return ans; }int head[N], to[N << 1], nex[N << 1], cnt = 1;int fa[N], son[N], sz[N], top[N], dep[N], rk[N], id[N], tot;int a[N << 1], b[N << 1], v[N << 1], n, m;void add(int x, int y) {to[cnt] = y;nex[cnt] = head[x];head[x] = cnt++; }void dfs1(int rt, int f) {fa[rt] = f, dep[rt] = dep[f] + 1, sz[rt] = 1;for (int i = head[rt]; i; i = nex[i]) {if (to[i] == f) {continue;}dfs1(to[i], rt);sz[rt] += sz[to[i]];if (!son[rt] || sz[son[rt]] < sz[to[i]]) {son[rt] = to[i];}} }void dfs2(int rt, int tp) {top[rt] = tp, rk[++tot] = rt, id[rt] = tot;if (!son[rt]) {return ;}dfs2(son[rt], tp);for (int i = head[rt]; i; i = nex[i]) {if (to[i] == fa[rt] || to[i] == son[rt]) {continue;}dfs2(to[i], to[i]);} }typedef pair<int, int> pii;pii sec[N];void update(int x, int y, int v, int op) {int cnt = 0;while (top[x] != top[y]) {if (dep[top[x]] < dep[top[y]]) {swap(x, y);}sec[++cnt] = make_pair(id[top[x]], id[x]);x = fa[top[x]];}if (dep[x] > dep[y]) {swap(x, y);}sec[++cnt] = make_pair(id[x], id[y]);sort(sec + 1, sec + 1 + cnt);int l = 0;for (int i = 1; i <= cnt; i++) {if (l + 1 < sec[i].first) {update(1, 1, n, l + 1, sec[i].first - 1, v, op);}l = sec[i].second;}if (l < n) {update(1, 1, n, l + 1, n, v, op);} }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);scanf("%d %d", &n, &m);for (int i = 1; i < n; i++) {int x, y;scanf("%d %d", &x, &y);add(x, y);add(y, x);}dfs1(1, 0);dfs2(1, 1);build(1, 1, n);for (int i = 1; i <= m; i++) {int op, x;scanf("%d", &op);if (op == 0) {scanf("%d %d %d", &a[i], &b[i], &v[i]);update(a[i], b[i], v[i], 1);}else if (op == 1) {scanf("%d", &x);update(a[x], b[x], v[x], 0);}else {scanf("%d", &x);printf("%d\n", query(1, 1, n, id[x], id[x]));}}return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的P3250 [HNOI2016]网络(利用堆建线段树 + 树剖)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。