設\(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祖先時 乘法原...