FROM WOJ 4317 談笑風生

2021-09-25 19:04:16 字數 2103 閱讀 5753

bzoj3653

題面

設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)滿足:

a、b和 c為 t 中三個不同的點,且 a為p 號節點;

a和b 都比 c不知道高明到**去了;

a和b 談笑風生。這裡談笑風生中的常數為給定的 k。

輸入

第一行含有兩個正整數n和q,分別代表有根樹的點數與詢問的個數。

接下來n - 1行,每行描述一條樹上的邊。每行含有兩個整數u和v,代表在節點u和v之間有一條邊。

接下來q行,每行描述乙個操作。第i行含有兩個整數,分別表示第i個詢問的p和k。

1<=p<=n

1<=k<=n

n<=300000

q<=300000

輸出

輸出 q 行,每行對應乙個詢問,代表詢問的答案。

樣例輸入

5 31 2

1 32 4

4 52 2

4 12 3

樣例輸出31

3sol

1.若b是a的祖先,就是a的size乘上a的祖先有多少個可以為b

2.若b是a的兒子,那就是a子樹的所有距離a不超過k的點的size之和,f[i][j]表示i子樹距i小於等於j的所有點的size之和,用長鏈剖分優化即可

**:

#include

using

namespace std;

#define re register

#define int long long

inline

intrd()

inline

void

write

(int x)

const

int n=

3e5+5;

int n,q,cnt,first[n]

,siz[n]

,fa[n]

,len[n]

,lson[n]

,dep[n]

;int tmp[n]

,*f[n]

,*id=tmp,ans[n]

;bool vis[n]

;struct nodee[n<<1]

;inline

void

add(

int u,

int v)

;first[u]

=cnt;

}struct query

;vectorq[n]

;void

dfs(

int u)

if(lson[u]

)len[u]

=len[lson[u]];

}void

solve

(int u)

for(

int re i=q[u]

.size()

-1ll

;~i;i--)}

signed

main()

dep[1]

=1,dfs(1

);for(

int re i=

1;i<=q;i++))

;}f[1

]=id,id+

=len[1]

,solve(1

);for(

int re i=

1;i<=q;i++

)write

(ans[i]),

putchar

('\n');

return0;

}

3653 談笑風生

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

湖南集訓 談笑風生

嘟嘟嘟 這題剛開始猶豫了一會兒,以為 高明 的優先順序大於 談笑風生 不過樣例表明只要兩點間距離不超過 x 兩人就算 談笑風生 接下來看看怎麼回答詢問。首先 a 是固定的,且 a,b 都是 c 的祖先。那就得分類討論 1.b 是 a 的祖先,那麼 c 就是 a 的子樹中的所有點,根據乘法原理,三元組...

BZOJ3653 談笑風生

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