3653: 谈笑风生
2016-05-20 17:20
281 查看
3653: 谈笑风生
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 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 31 2
1 3
2 4
4 5
2 2
4 1
2 3
Sample Output
31
3
HINT
1<=P<=N1<=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 YZY
freopen("yzy.txt","r",stdin);
#endif
cin >> 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;
}
相关文章推荐
- ffmpeg文档37-视频滤镜
- 今天上qq空间看到一个有意思的东西,类似射线的效果
- 如何用PPT制作多媒体光盘
- C# 窗体应用 随机数猜大小
- ReactOS-Freeldr注册表HIVE文件格式
- uva839-Not so Mobile-二叉树的DFS
- 数字字符串转为指定数组
- iOS面试那点事
- Apple Watch程序开发30分钟秒懂
- 实现鼠标穿透窗体
- hibernate复合查询
- 深入Java集合学习系列:ArrayList的实现原理
- 【mysql】order by 优化与索引的应用
- SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
- Notepad++ 快捷键 大全
- FFmpeg Filtering Guide
- ckplayer 中的style.swf 中的 style.xml 中的修改方法
- 加速Android Studio/Gradle构建
- XSI IPC之消息队列实例
- Tensorflow source build on MAC EI Capitain