CTSC2018 暴力寫掛

2022-03-26 22:32:52 字數 1516 閱讀 6132

題目

邊分治+虛樹=雙倍的快樂

這個柿子裡有兩個\(lca\),我們考慮魔改一下前面的\(\operatorname\),為了方便邊分,我們考慮把\(\operatorname\)去掉變換為樹上距離

經過一番魔改,這個柿子變成了\(\frac(\operatorname)\)

至於第二棵樹上的\(\operatorname\),我們只能考慮到虛樹上去搞了

對於當前的分治邊\(w\),我們處理處分塊內所有點\(i\)到這條邊的距離\(p_i\),那麼\(\operatorname=p_x+p_y+w+depth_x+depth_y\)

同時我們把分治邊左右兩邊的點黑白染色,點權設為\(p_i+depth_i\),到第二顆樹上去建虛樹,對於虛樹上的每個點考慮其作為\(\operatorname\)時的貢獻,於是把問題轉化成了在乙個點的不同兒子裡找到一對異色點,使得點權最大,顯然直接虛樹上dp就好了

如果虛樹實現得不好,這個演算法就是\(\operatorname\)

如果使用st表求\(\operatorname\),並且在一開始就把所有點按照\(\operatorname\)排序,每次根據這個點染成的顏色分到兩個接下來的分治塊裡去,就能做到線性建虛樹,整個演算法的複雜度就能到\(\operatorname\)

記得特判\(x=y\)的情況

**

#include#define re register

#define ll long long

#define pt putchar(1)

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)<(b)?(a):(b))

const int maxn=366667;

const int m=maxn*4;

const ll inf=-1e15;

inline int read()

while(c>='0'&&c<='9') x=(x<<3ll)+(x<<1ll)+c-48,c=getchar();return r*x;

}std::vectorson[m];

std::vectorv[m];

struct ee[m<<1];

int head[m],sum[m],vis[m],dfn[maxn],b[maxn];

int s,mnow,rn,n,num,col[maxn],rt,mnow,tp[2],c[2][maxn];

ll g[maxn],dp[maxn][2],deep[maxn],tmp,ans;

inline int cmp(int a,int b)

void tree_dp(int x)

} inline void get_tree(int l,int r)

void del(int x)

}t;void dfs2(int x,int fa,int o,ll d)

}void solve(int x,int s,int l,int r)

int main()

CTSC2018 暴力寫掛

題目鏈結 ctsc2018 暴力寫掛 做法 dep x dep y dep lca x,y dep lca x,y frac dep x dep y 2dep lca x,y dep x dep y 2dep lca x,y frac dis x,y dep x dep y 2dep lca x,y...

CTSC2018 暴力寫掛 邊分樹合併

ctsc2018 暴力寫掛 題面不錯 給定兩棵樹,兩點 距離 定義為 二者深度相加,減去兩棵樹上的lca的深度 深度指到根節點的距離 求最大的距離。解決多棵樹的問題就是降維了。經典的做法是邊分樹合併。邊分樹結構類似0 1 trie 就是把邊分樹對於每個點拆開路徑 合併兩棵邊分樹同時可以得到兩個邊分樹...

WC2018 通道 與 CTSC2018 暴力寫掛

兩個都給出點分治的做法,看起來邊分治不光跑的慢還沒什麼不可替代性?暴力寫掛 考慮那個式子有兩個不同樹上的 operatorname 不好處理,考慮怎麼換成乙個 由於 dis x,y deep x deep y 2deep operatorname x,y 於是用 dis 代換 dfrac dis x...