luogu3899談笑風生

2022-05-08 00:54:08 字數 1191 閱讀 4195

設\(t\)為一棵有根樹,我們做如下的定義:

給定一棵\(n\)個節點的有根樹\(t\),節點的編號為\(1-n\),根節點為\(1\)號節點。你需要回答\(q\)個詢問,詢問給定兩個整數\(p\) 和\(k\),問有多少個有序三元組\((a,b,c)\)滿足:

題面真有趣

有乙個很套路的樹狀陣列離線做法:(我在這題的部落格裡提過一遍)

按照中序遍歷\(dfs\),每到乙個點,先減去自己的子樹以外的影響(樹狀陣列詢問一下),然後再把這個點加進樹狀陣列。

這樣當每個點的子樹被遍歷完時,用當前得到的答案,減去上一次得到的答案,就是自己的子樹對答案的貢獻。

既然上次我寫了線段樹合併,這次就離線演算法舒服一下:

(然後因樹狀陣列內上限設為\(n\),\(gg\)了不知道多少回。。。)

#include#include#include#include#include#include#include#define ll long long

#define re register

#define il inline

#define pb(a) push_back(a)

#define fp(i,a,b) for(re int i=a;i<=b;i++)

#define fq(i,a,b) for(re int i=a;i>=b;i--)

using namespace std;

const int n=3e5+100;

int n,q,h[n],cnt,sz[n],d[n];

ll t[n],ans[n];

vectorq[n],id[n];

struct edgee[n<<1];

il void add(re int u,re int v);h[u]=cnt;}

il void mod(re int x,re int w)

il ll que(re int x)

il ll gi()

il void dfs(re int u,re int fa)

for(re int i=0;imod(d[u],sz[u]-1);

}int main()

fp(i,1,q)

dfs(1,0);

fp(i,1,q) printf("%lld\n",ans[i]);

return 0;

}

luogu 3899 湖南集訓 談笑風生

題意 這題意太草了就不描述了,有黑眼鏡框和 暗示真惡毒啊 sol 對於固定的a來說,每個b的貢獻是min siza siz b 1 min siz a,siz b 1 min si za sizb 1 考慮a是b的祖先和b是a的祖先兩種情況 把min去掉 1.對於b是a的祖先,明顯答案是min de...

P3899 湖南集訓 談笑風生

傳送門 首先 a,b,c 肯定在一條鏈上。當 b 為 a 的祖先時,a 的子樹中所有與它不同的點都可以作為點 c 當 a 為 b 的祖先時,b 的子樹中所有與它不同的點都可以作為答案 我會說我以前根本沒寫過線段樹合併結果完全不知道錯在 麼 luogu judger enable o2 minamot...

P3899 湖南集訓 談笑風生

題目大意 n個節點的樹,q次查詢,每次查詢給出a,k求三元組的數量 a,b,c a,b,c 的定義為 a b均為c的祖先且距離 k 離線,啟發式合併線段樹,長鏈剖分當然都能過這題 這裡講講主席樹的做法 dfs序建樹 a為b的祖先時 查詢a子樹內深度 dep a k的節點的子樹和 b為a祖先時 乘法原...