BZOJ3653 談笑風生(長鏈剖分)

2022-03-20 04:57:45 字數 1401 閱讀 8476

bzoj

洛谷許可權題啊。。。。

首先根據題目給的條件,發現\(a,b\)都要是\(c\)的父親。

所以這三個點是樹上的一條深度單增的鏈。

因為\(a,b\)之間距離不超過\(k\),並且\(a\)被欽定了,所以只有兩種情況:

一種是\(a\)是\(b\)的祖先,貢獻是\(\sum_b size[b]-1\),也就是所有\(b\)可以選擇的點的子樹和。

另外一種\(b\)是\(a\)的祖先,貢獻是\(\sum_b size[a]-1\),欽定乙個\(b\)之後,\(c\)可以在\(a\)的子樹中任選。

第二種情況很簡單,因為\(size[a]\)是定值,並且每個點的父親是唯一的,所以第二部分很容易算。

困難的是第一部分,然而依舊不難把。。。

方法很多,比如說,你把\(dfs\)序和深度看成\(x,y\)軸,這樣子就是二維數點,直接主席樹。

或者說直接點分治也可以。

當然,既然想寫長鏈剖分,那就當然要用長鏈剖分來做啊。

我們發現,所有的值都由重兒子向後挪動一位得來,而我們要求的東西需要維護乙個區間和。

這樣子很不好用字首和來做,所以我們可以用乙個字尾和啊!

這樣子就很舒服了,直接維護字尾和,然後長鏈剖分轉移,可以做到複雜度\(o(n)\)。

#include#include#include#include#include#include#includeusing namespace std;

#define ll long long

#define max 300300

inline int read()

struct ask;

vectorp[max];

struct linee[max<<1];

int h[max],cnt=1;

inline void add(int u,int v);h[u]=cnt++;}

ll tmp[max],*s[max],*id=tmp,ans[max];

int md[max],dep[max],fa[max],hson[max],size[max];

void dfs1(int u,int ff)

if(hson[u])md[u]=md[hson[u]];

}void dfs(int u)

for(int i=p[u].size()-1;~i;--i) }

int n,q;

int main()

dfs1(1,0);

for(int i=1;i<=q;++i)

); }

s[1]=id;id+=md[1];dfs(1);

for(int i=1;i<=q;++i)printf("%lld\n",ans[i]);

return 0;

}

BZOJ3653 談笑風生

對於每乙個詢問我們可以提出 ans min dep u 1,k size u 1 u子樹中到u距離 k的節點的子樹節點和 顯然後面那個東西是可以用可持久化線段樹搞得 好了 include include include include using namespace std char c defin...

BZOJ3653 談笑風生

題目大意 給一棵樹,每次詢問給定a,k,求三元組 a,b,c 的數量滿足 1.a和b都是c的祖先 2.a和b在樹上距離不超過k 3.a,b,c互不相同 顯然abc肯定形成豎著的一條鏈 分兩種情況討論 1.b在a的上方,也就是說對於任意合法的b,c可以在a的子樹裡隨便選,這個方案數是可以直接算出來的 ...

BZOJ 3653 談笑風生

題目在這裡呀!個人認為是一道很好的題目,原來可持久化線段樹還能這麼用,看題解之前還是沒有想到啦要批評!那就寫個題解補償一下?給你一棵有根樹,n個節點,有q次詢問,每次詢問,給出兩個數x 1 x n d,求有多少有序元組 y,z 滿足 x,y,z互不相同,x,y均為z的祖先,且x,y之間的距離超過d。...