題解 星系探索

2022-05-01 19:51:11 字數 1698 閱讀 1255

題目傳送門

給出乙個 \(n\) 個點的樹,每個點有點權,有 \(m\) 次操作,分別為以下操作:

\(n\le 100000,m\le 300000\),保證答案在\(\text\)範圍以內。

這似乎是個假的 \(\text\) ,似乎真的 \(\text\) 是用尤拉迴路做的,但是它並不能維護鏈的資訊,但可以支援換根。雖然還是沒有 \(\text\) 強(儘管我完全不會(大喊 \(\texttt\) 老爺子牛逼!!! 好了,還是來講這道題吧

我們發現其實難點就在於如何維護 \(1\to u\) 的鏈的點權和,我們可以發現其實這個可以用尤拉序(似乎也叫做括號序)維護,然後更改某個點的父親其實可以用 \(\text\) 將該區間的尤拉序移到其它點下面去。然後我們驚奇地發現我們就做完了。

時間複雜度 \(\theta(n+m\log n)\) ,為了方便我在前後各加了兩個哨兵,能保證找到前驅後繼。

#include using namespace std;

#define int register int

#define ll long long

#define maxn 200005

template inline void read (t &t)while (c >= '0' && c <= '9') t *= f;}

template inline void read (t &t,args&... args)

template inline void write (t x)if (x > 9) write (x / 10);putchar (x % 10 + '0');}

ll sum[maxn],tag[maxn];

int n,m,root,son[maxn][2],par[maxn],val[maxn],exi[maxn],siz[maxn];

bool rnk (int x)

void connect (int f,int now,int typ)

void pushup (int x)

void pushdown (int x)

}void rotate (int x)

int tot,s[maxn];

void splay (int x,int to)

void query (int x)

int pre (int x)

int suc (int x)

void modify (int l,int r,ll v)

void change (int l,int r,int to)

int index = 1,top = 1,a[maxn],to[maxn],nxt[maxn],head[maxn],dfn[maxn],low[maxn];

void add_edge (int u,int v)

void dfs (int u)

int build (int l,int r)

signed main();scanf ("%s",s);

if (s[0] == 'q') read (x),query (pre (low[x]));

else if (s[0] == 'c') read (x,y),change (dfn[x],low[x],dfn[y]);

else read (x,y),modify (dfn[x],low[x],y);

} return 0;

}

BZOJ3786 星系探索

ett搞上,每條邊如果是一條從父到子的邊,那麼設其權值為兒子節點的權值,如果是一條從子到父的邊,那麼設其權值為兒子節點的權值的相反數,我們用乙個splay來維護整棵樹的尤拉序,那麼乙個節點到根的路徑的點權和就等於從根走尤拉序到這個點的邊權和 linkcut操作就相當於區間平移 子樹加就相當於把區間裡...

BZOJ3786 星系探索

一道ett板子題 筆者最開始用fhq treap打的ett,忘記可以沿fafa fa算出它的尤拉序,一直沒調出來,於是就改用splay了。ett的模板。其實我覺得叫它平衡樹板子就可以了 我們可以先通過尤拉序建出一顆平衡樹來,令inx in in x 為點x xx的入尤拉序,out xout outx...

BZOJ 3786 星系探索

bzoj 3786 星系探索 splay維護出棧入棧序 物理學家小c的研究正遇到某個瓶頸。他正在研究的是乙個星系,這個星系中有n個星球,其中有乙個主星球 方便起見我們預設其為1號星球 其餘的所有星球均有且僅有乙個依賴星球。主星球沒有依賴星球。我們定義依賴關係如下 若星球a的依賴星球是b,則有星球a依...