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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【LCT】【树状数组】Matches Are Not a Child‘s Play(luogu CF1137F)

發布時間:2023/12/3 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【LCT】【树状数组】Matches Are Not a Child‘s Play(luogu CF1137F) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

luogu CF1137F


題目大意

定義一棵樹的產出序列為依次刪除權值最小的葉子節點的順序
進行q此操作:
1.把一個點的權值改為當前樹中的最大權值+1
2.查詢一個點在刪除序列中的位置
3.給出兩個點,查詢哪個在刪除序列中的位置更前


解題思路

假設已經求出了刪除序列,且最大權值的點為y,那么修改一個點x,相當于把x~y上的點放到序列后面(對于其它點,必然不是在x或y刪除后再刪除的)

這就是要提取出一條樹鏈,可以使用LCT

以權值最大的點為根節點,一個點往上若干個權值比它小的點為一條鏈,因為這些點要會當前點刪除后依次刪除(當前點刪除了,那么其它葉子結點一定都大于當前點,也就大于鏈上其它點)

給這條鏈上的所有點的顏色染上鏈上最深點的權值

那么查詢就相當于查找顏色比當它小的點的個數加上鏈上比它深的點的個數

修改就相當于連接x~y的鏈,換根,染色

對于查找顏色比它小的點用樹狀數組即可


代碼

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 200021 using namespace std; int n, q, x, y, w, tot, cl[N], head[N]; string str; struct rec {int to, next; }a[N<<1]; struct tree//樹狀數組 {int n, c[N<<1];void change(int x, int y){for (; x <= n; x += x&-x)c[x] += y;return;}int ask(int x){int sum = 0;for (; x; x -= x&-x)sum += c[x];return sum;} }t; struct LCT {int p[N], fa[N], sz[N], son[N][2];bool NR(int x){return fa[x] && (son[fa[x]][0] == x || son[fa[x]][1] == x);}bool IRS(int x){return son[fa[x]][1] == x;}void push_up(int x){sz[x] = sz[son[x][0]] + sz[son[x][1]] + 1;return;}void pushr(int x){p[x] ^= 1;swap(son[x][0], son[x][1]);return;}void push_down(int x){if (son[x][0]) cl[son[x][0]] = cl[x];//顏色if (son[x][1]) cl[son[x][1]] = cl[x];if (p[x]){if (son[x][0]) pushr(son[x][0]);if (son[x][1]) pushr(son[x][1]);p[x] = 0;}return;}void push_hall(int x){if (NR(x)) push_hall(fa[x]);push_down(x);return;}void rotate(int x){int y = fa[x], z = fa[y], k = IRS(x), g = son[x][!k];if (NR(y)) son[z][IRS(y)] = x;if (g) fa[g] = y;fa[x] = z;fa[y] = x;son[x][!k] = y;son[y][k] = g;push_up(y);return;}void Splay(int x){push_hall(x);while(NR(x)){if (NR(fa[x])) rotate(IRS(x) == IRS(fa[x]) ? fa[x] : x);rotate(x);}push_up(x);}void access(int x){for (int y = 0; x; x = fa[y = x]){Splay(x);son[x][1] = 0;push_up(x);t.change(cl[x], -sz[x]);//減去原來的顏色t.change(w, sz[x]);//改成現在的顏色son[x][1] = y;push_up(x);}return;}void make_root(int x){w++;access(x);Splay(x);cl[x] = w;//染色pushr(x);return;}int ask(int x){Splay(x);return sz[son[x][1]] + 1 + t.ask(cl[x] - 1);} }T; void add(int x, int y) {a[++tot].to = y;a[tot].next = head[x];head[x] = tot;return; } void dfs(int x) {cl[x] = x;for (int i = head[x]; i; i = a[i].next)if (!cl[a[i].to]){T.fa[a[i].to] = x;dfs(a[i].to);if (cl[a[i].to] > cl[x]){cl[x] = cl[a[i].to];T.son[x][1] = a[i].to;}}t.change(cl[x], 1);T.push_up(x);return; } int main() {scanf("%d%d", &n, &q);for (int i = 1; i < n; ++i){scanf("%d%d", &x, &y);add(x, y);add(y, x);}t.n = n + q;w = n;dfs(n);//連初始的圖while(q--){cin>>str;if (str == "up"){scanf("%d", &x);T.make_root(x);}else if (str == "when"){scanf("%d", &x);printf("%d\n", T.ask(x));}else{scanf("%d%d", &x, &y);printf("%d\n", T.ask(x) < T.ask(y) ? x : y);}}return 0; }

總結

以上是生活随笔為你收集整理的【LCT】【树状数组】Matches Are Not a Child‘s Play(luogu CF1137F)的全部內容,希望文章能夠幫你解決所遇到的問題。

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