3653: 谈笑风生

来源:互联网 发布:淘宝接单的app都有哪些 编辑:程序博客网 时间:2024/06/05 12:44

3653: 谈笑风生

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 498  Solved: 185
[Submit][Status][Discuss]

Description

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

Input

输入文件的第一行含有两个正整数n和q,分别代表有根树的点数与询问的个数。接下来n - 1行,每行描述一条树上的边。每行含有两个整数u和v,代表在节点u和v之间有一条边。
接下来q行,每行描述一个操作。第i行含有两个整数,分别表示第i个询问的p和k。


Output

输出 q 行,每行对应一个询问,代表询问的答案。

Sample Input

5 3
1 2
1 3
2 4
4 5
2 2
4 1
2 3

Sample Output


3
1
3

HINT


1<=P<=N

1<=K<=N

N<=300000

Q<=300000

Source

[Submit][Status][Discuss]





维护dfs序的线段树

每次询问的b要么在a上面(每组的权值是size[a])要么在a下面(每组权值size[b])

然后距离都不超过k

第一种很好处理

第二种在线段树一段区间里面还需满足深度符合

也就是线段树需要两个关键字判断(dfs序与深度)

这样的询问每次是O(log^2)的


一开始也不知道为什么想bfs序?显然不可以

然后query函数里面没及时return 0


#include<iostream>#include<cstdio>#include<queue>#include<vector>using 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 <int> v[maxn];void build(int o,int l,int r,int pos,int Add,int de){if (l == r) {c[o] = Add; ac[o] = bc[o] = de; return;}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){dfi[k] = ++clo; for (int i = 0; i < v[k].size(); i++) {int to = v[k][i];if (L[to]) continue;L[to] = L[k] + 1;dfs(to);siz[k] += siz[to] + 1;}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){if (ql <= l && r <= qr && qa <= ac[o] && bc[o] <= qb) return c[o];if (bc[o] < qa || qb < ac[o]) return 0;int mid = (l+r) >> 1; LL ret = 0;if (ql <= mid) ret += query(2*o,l,mid,ql,qr,qa,qb);if (qr > mid) ret += query(2*o+1,mid+1,r,ql,qr,qa,qb);return ret;}int main(){#ifdef YZYfreopen("yzy.txt","r",stdin);#endifcin >> n >> m; for (int i = 1; i < n; i++) {int x,y; scanf("%d%d",&x,&y);v[x].push_back(y); v[y].push_back(x);}clo = 0; L[1] = 1; dfs(1); while (m--) {int p,k; LL ans; scanf("%d%d",&p,&k);if (L[p] - k >= 1) ans = 1LL*k*1LL*siz[p];else ans = 1LL*(L[p]-1)*1LL*siz[p];if (dfi[p] + 1 <= dfo[p]) ans += query(1,1,n,dfi[p]+1,dfo[p],L[p] + 1,L[p] + k);printf("%lld\n",ans);}return 0;}


0 0
原创粉丝点击