BZOJ3779 重組病毒

2022-05-07 22:42:13 字數 1463 閱讀 2236

題面:許可權題,去網上看題面吧。

這題可能是出題人比著lct出的吧。。。

發現每一次的release與access操作極為神似,recenter更是貼心的為你附加了一次release,

這不就是makeroot中的一次access嗎。。。那我們考慮統計答案,發現就是那乙個點到當前根節點之間虛邊的數量,那麼我們用樹狀陣列維護,每一次將對應的子樹在\(dfs\)序上連續的一段+1或-1即可。

#include#include#include#define n 100005

#define lc c[x][0]

#define rc c[x][1]

#define ll long long

using namespace std;

const int nlog=16;

inline int in()

int n,m,h[n],e_tot=0;

struct ee[n<<1];

inline void add(int u,int v); h[u]=e_tot;

e[++e_tot]=(e); h[v]=e_tot;

}ll sum1[n],sum2[n];

inline int lb(int x)

inline void add1(int x,int c)

inline ll sum1(int x)

inline void add2(int x,int c)

inline ll sum2(int x)

inline void modify(int l,int r,int c)

inline ll query(int l,int r)

int sz[n],dfn[n],dfs_clock=0,f[n];

int fa[n][nlog+5],d[n];

void dfs(int u,int pre,int dep)

modify(dfn[u],dfn[u]+sz[u]-1,1);

}inline int lca(int x,int y,int& pos)

return fa[pos=x][0];

}int c[n][2],r[n],rt;

inline bool nrt(int x)

inline void pushdown(int x)

}inline void modify(int x,int c)

inline double query(int x)

inline void rotate(int x)

inline void pushall(int x)

inline void splay(int x)

}inline void access(int x)

}inline void makeroot(int x)

int main()

return 0;

}

BZOJ3779 重組病毒

題目大意 給一棵樹,每個點一開始顏色互不相同,支援三個操作 1.將乙個點到根的路徑染成一種新的顏色 2.將乙個新的點設為根,並將原來的根到這個點的路徑染成一種新的顏色 3.查詢乙個子樹 對於當前根 到根的路徑期望顏色數 真tm是道神題,idea實在是太妙了 首先由於第2個操作的特殊性,我們可以發現,...

BZOJ3779 重組病毒

窮哭了 難嗎?難碼.首先觀察一下操作一,就是乙個access,但是要改變子樹啊,lct不緇瓷,所以線段樹稍微維護一下。怎麼維護是乙個大難點啊。是要分類討論的。先找出實右子樹在原數上的根xxx。情況rt x rt x rt x 直接修改整顆樹。r trt rt在子樹中,令y r ty rt y rt ...

bzoj 3779 重組病毒

一道好題 乙個點到根傳染需要的時間是這段路徑上不同顏色的數目,乙個點子樹到根平均傳染時間就是加權平均數了 好像是廢話 所以只要用線段樹維護dfs序就這個可以了,換根的話乙個點的子樹要麼在dfs序中不變,要麼被截成了 1,l 和 r,n 兩段 當這個點為當前root的祖先 l和r即為包含當前根的這個點...