刷题总结——谈笑风生(主席树+dfs序的应用)
题目:
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
1 2
1 3
2 4
4 5
2 2
4 1
2 3
Sample Output
1
3
HINT
1<=P<=N
1<=K<=N
N<=300000
Q<=300000
题解:
线段树以深度为关键字维护size的和
x,y的答案 = size[x] * min(deep[x], y) + dfs序在l[x] + 1到r[x]之间且深度在deep[x] + 1到deep[x] + k之间的size和
挺有收获的一道题···第一次发现主席树每个节点的表示区间可以与其在第几棵树无关。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int read()
{
int x=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x;
}
const int N=3e5+;
struct node
{
int l,r;
long long size;
}tree[N<<];
int root[N],totr=;
int first[N],next[N*],go[N*],tot=;
int cnt=,que[N],in[N],out[N],deep[N],maxdeep=,size[N];
int n,q;
inline void comb(int a,int b)
{
next[++tot]=first[a],first[a]=tot,go[tot]=b;
next[++tot]=first[b],first[b]=tot,go[tot]=a;
}
inline void dfs(int u,int fa)
{
in[u]=++cnt;
size[u]=;
que[cnt]=u;
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==fa) continue;
deep[v]=deep[u]+;
maxdeep=max(maxdeep,deep[v]);
dfs(v,u);
size[u]+=size[v];
}
out[u]=cnt;
}
inline void build(int &now,int l,int r,int deep,int size)
{
tree[++totr]=tree[now],now=totr;
tree[now].size+=size;
if(l==r) return;
int mid=(l+r)/;
if(deep<=mid) build(tree[now].l,l,mid,deep,size);
if(deep>mid) build(tree[now].r,mid+,r,deep,size);
}
//------------------------------------
inline void Insert(const int &x, int &y, const int &l, const int &r, const int &pos, const int &v){
tree[y = ++totr] = tree[x];
tree[y].size += v;
if(l == r) return;
int mid = l + r >> ;
if(pos <= mid) Insert(tree[x].l, tree[y].l, l, mid, pos, v);
else Insert(tree[x].r, tree[y].r, mid + , r, pos, v);
}
//---------------------------------------
inline long long query(int k,int l,int r,int x,int y)
{
if(x <= l && r <= y)
return tree[k].size;
int mid=(l+r)/;
long long temp=;
if(x<=mid) temp+=query(tree[k].l,l,mid,x,y);
if(y>mid) temp+=query(tree[k].r,mid+,r,x,y);
return temp;
}
int main()
{
//freopen("a.in","r",stdin);
n=read();
q=read();
int a,b;
for(int i=;i<n;i++)
{
a=read();
b=read();
comb(a,b);
}
dfs(,);
for(int i=;i<=cnt;i++)
{
root[i]=root[i-];
build(root[i],,maxdeep,deep[que[i]],size[que[i]]-);
}
//for(int i = 1; i <= n; i++) Insert(root[i - 1], root[i], 0, maxdeep, deep[que[i]],size[que[i]]-1);
while(q--)
{
scanf("%d%d",&a,&b);
long long ans=;
ans+=(long long) (size[a]-)*(long long)min(deep[a],b);
ans+=query(root[out[a]],,maxdeep,min(deep[a]+,maxdeep),min(deep[a]+b,maxdeep));
ans-=query(root[in[a]-],,maxdeep,min(deep[a]+,maxdeep),min(deep[a]+b,maxdeep));
cout<<ans<<endl;
}
return ;
}
刷题总结——谈笑风生(主席树+dfs序的应用)的更多相关文章
- 51 nod 1681 公共祖先 (主席树+dfs序)
1681 公共祖先 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另 ...
- 【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序
[BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n n ...
- 【SPOJ】10628. Count on a tree(lca+主席树+dfs序)
http://www.spoj.com/problems/COT/ (速度很快,排到了rank6) 这题让我明白了人生T_T 我知道我为什么那么sb了. 调试一早上都在想人生. 唉. 太弱. 太弱. ...
- BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增
题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 321[Submit][Sta ...
- BZOJ 2809: [Apio2012]dispatching [主席树 DFS序]
传送门 题意:查询树上根节点值*子树中权值和$\le m$的最大数量 最大值是多少 求$DFS$序,然后变成区间中和$\le m$最多有几个元素,建主席树,然后权值线段树上二分就行了 $WA$:又把边 ...
- BZOJ - 2809 dispatching 主席树+dfs序
在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同时增强忍者们的 ...
- BZOJ3772 精神污染 主席树 dfs序
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3772 题意概括 给出一个树,共n个节点. 有m条互不相同的树上路径. 现在让你随机选择2条路径,问 ...
- BZOJ5338[TJOI2018]xor——主席树+dfs序
题目描述 现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值vi. 现在有Q 次操作,操作如下: 1 x y 查询节点x的子树中与y异或结果的最大值 2 x y z ...
随机推荐
- [总结].net操作MongoDb通用基础类1:
public class MongoDBHelper { //定义Mongo服务 private MongoServer mongo = null; //获取databaseName对应的数据库,不存 ...
- SQLServer外键查询删除信息
SELECT FK.NAME,FK.OBJECT_ID,OBJECT_NAME(FK.PARENT_OBJECT_ID) AS REFERENCETABLENAMEFROM SYS.FOREIGN_K ...
- C++和ASM文件的互相调用
1. C++调用ASM中的函数,需要在ASM源文件中指定.model flat, c 就是指定以C的形式编译,然后在头文件中用EXTERN_C声明这个头文件就可以了 2. ASM中调用C++函数,需要 ...
- org.thymeleaf.exceptions.TemplateInputException: Error resolving template "/home/index2", template might not exist or might not be accessible by any of the configured Template Resolvers
org.thymeleaf.exceptions.TemplateInputException: Error resolving template "/home/index2", ...
- DP一直是自己的弱势 开始练滚动数组——HDOJ4502
http://acm.hdu.edu.cn/showproblem.php?pid=4502//题目链接 思路 : dp[i]表示 到第i天能获得的最大工资 依次更新 #include<cst ...
- stringstream类的简介和用法
一.简介 <sstream>类库定义了三种类:istringstream,ostringstream,stringstream.分别用来进行流的输入,流的输出,输入输出操作.在此演示str ...
- pwntools学习
0x00 数据处理 主要是对整数进行打包,就是转换成二进制的形式,比如转换成地址.p是打包,u是解包 32位:p32,u32 64位:p64,u64 0x01 汇编与反汇编 1.asm 进行汇编,使用 ...
- shell脚本,如何监控目录下的文件内容是否被修改。
第一种方法是通过cmp来进行比对[root@localhost bo]# ls .html .html .html .html .html .html .html .html .html cat.sh ...
- 解析Java finally
以下用几个简单的例子介绍一下finally的用法: 例子1 public class Test { public static void main(String[] args) { System.ou ...
- i.mx53开发的一些问题
i.mx53开发的一些问题 转载于此:http://blog.csdn.net/shell_albert/article/details/8242288 原来i.mx53上4GB的Nand Fla ...