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。...