time limit: 20 sec
memory limit: 512 mb
submit: 498
solved: 185 [
submit][
status][
discuss]
設t 為一棵有根樹,我們做如下的定義:
• 設a和b為t 中的兩個不同節點。如果a是b的祖先,那麼稱「a比b不知道
高明到**去了」。
• 設a 和 b 為 t 中的兩個不同節點。如果 a 與 b 在樹上的距離不超過某個給定
常數x,那麼稱「a 與b 談笑風生」。
給定一棵n個節點的有根樹t,節點的編號為1 到 n,根節點為1號節點。你需
要回答q 個詢問,詢問給定兩個整數p和k,問有多少個有序三元組(a;b;c)滿足:
1. a、b和 c為 t 中三個不同的點,且 a為p 號節點;
2. a和b 都比 c不知道高明到**去了;
3. a和b 談笑風生。這裡談笑風生中的常數為給定的 k。
輸入檔案的第一行含有兩個正整數n和q,分別代表有根樹的點數與詢問的個數。接下來n - 1行,每行描述一條樹上的邊。每行含有兩個整數u和v,代表在節點u和v之間有一條邊。
接下來q行,每行描述乙個操作。第i行含有兩個整數,分別表示第i個詢問的p和k。
輸出 q 行,每行對應乙個詢問,代表詢問的答案。
5 31 2
1 32 4
4 52 2
4 12 331
31<=p<=n
1<=k<=n
n<=300000
q<=300000
[submit][
status][
discuss]
維護dfs序的線段樹
每次詢問的b要麼在a上面(每組的權值是size[a])要麼在a下面(每組權值size[b])
然後距離都不超過k
第一種很好處理
也就是線段樹需要兩個關鍵字判斷(dfs序與深度)
這樣的詢問每次是o(log^2)的
一開始也不知道為什麼想bfs序?顯然不可以
然後query函式裡面沒及時return 0
#include#include#include#includeusing namespace std;
const int maxn = 4e5 + 30;
typedef long long ll;
int n,m,p,k,clo,dfi[maxn],dfo[maxn],siz[maxn],l[maxn];
ll c[maxn*20];
int ac[maxn*20],bc[maxn*20];
vector v[maxn];
void build(int o,int l,int r,int pos,int add,int de)
int mid = (l+r) >> 1;
if (pos <= mid) build(2*o,l,mid,pos,add,de);
else build(2*o+1,mid+1,r,pos,add,de);
c[o] = c[2*o] + c[2*o+1];
ac[o] = min(ac[2*o],ac[2*o+1]);
bc[o] = max(bc[2*o],bc[2*o+1]);
}void dfs(int k)
dfo[k] = clo;
build(1,1,n,dfi[k],siz[k],l[k]);
}ll query(int o,int l,int r,int ql,int qr,int qa,int qb)
int main()
clo = 0; l[1] = 1; dfs(1);
while (m--)
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。...