牛客 NOIp模拟1 T3 保护 解题报告
保护
题目描述
\(C\)国有\(n\)个城市,城市间通过一个树形结构形成一个连通图。城市编号为\(1\)到\(n\),其中\(1\)号城市为首都。国家有\(m\)支军队,分别守卫一条路径的城市。具体来说,对于军队\(i\),他守卫的城市区域可以由一对二元组\((x_i,y_i)\)代表。表示对于所有在\(x_i\)到\(y_i\)的最短路径上的城市,军队\(i\)都会守卫他们。
现在有\(q\)个重要人物。对于一个重要人物\(j\),他要从他的辖区\(v_j\)出发,去到首都。出于某些原因,他希望找到一个离首都最近的,且在\(v_j\)到首都路径上的城市\(u_j\),使得至少有\(k_j\)支军队,能够全程保护他从\(v_j\)到\(u_j\)上所经过的所有城市。换句话说,至少有\(k_i\)支军队,满足在树上,\(x_i\)到\(y_i\)的路径能完全覆盖掉\(v_j\)到\(u_j\)的路径。
输入描述:
第一行输入两个数\(n\),\(m\)。
接下来\(n-1\)行,每行两个整数\(u\),\(v\),表示存在一条从城市\(u\)到城市\(v\)的道路。
接下来\(m\)行,每行两个整数\(x\),\(y\)。描述一个军队的守卫区域。
接下来一行一个整数\(q\)。
接下来\(q\)行,每行两个整数\(v_j,k_j\)。
输出描述:
对于每次询问,输出从\(v_j\)到\(u_j\)最少需要经过多少条边。假如不存在这样的\(u_j\),则输出\(0\)。
备注:
20%: n,m,q <= 300
40%: n,m,q <= 2000
60%: n,m,q <= 50000
100%: n,m,q <= 200000
覆盖必须是完全覆盖,不可以每个军队保护不同的段
设军队有为三元组\((x,y,z)\)
其中,\(x,y\)为军队的链端点,\(z\)为它们的\(LCA\)的深度
可以知道,每次询问\((v,k)\)都是查询满足\(dfn_v \le x \le low_v\)或\(dfn_v \le y \le low_v\)的第\(k\)小\(z\)值
\(dfn_v\)~\(low_v\)是整棵子树的dfs序
可以直接CDQ套主席树求解
upd:不需要套CDQ,借助差分的思想,主席树就可以解决 有一道基本一样的题可以看看[CQOI2015]任务查询系统
然而也可以用神奇的启发式合并
对每个节点建一颗权值线段树,代表这个节点的子树所包含的\(x\)或\(y\)的\(z\)值集合
注意这里并不需要容斥,因为如果\(x,y\)在同一颗子树那它们一定无法对这个子树根做出贡献
具体的,我们可以建出每个节点自己的\(z\)值集合,然后dfs合并上去
我这里直接用了子树的节点,所以会破坏子树的结构,于是先读进来然后离线做了
在线也可以,不过要多开一些节点
Code:
#include <cstdio>
#include <vector>
using namespace std;
const int N=2e5+10;
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v)
{
to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
int f[N][19],dep[N],n,m,q;
void dfs_(int now)
{
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v!=f[now][0])
{
f[v][0]=now;
dep[v]=dep[now]+1;
for(int j=1;j<=18;j++)
f[v][j]=f[f[v][j-1]][j-1];
dfs_(v);
}
}
}
vector <int > d[N];
int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=18;~i;i--)
if(dep[f[x][i]]>=dep[y])
x=f[x][i];
if(x==y) return x;
for(int i=18;~i;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
int sum[N*30],ch[N*30][2],tot,root[N];
#define ls ch[now][0]
#define rs ch[now][1]
void change(int &now,int l,int r,int pos)
{
if(!now) now=++tot;
if(l==r) {++sum[now];return;}
int mid=l+r>>1;
if(pos<=mid) change(ls,l,mid,pos);
else change(rs,mid+1,r,pos);
sum[now]=sum[ls]+sum[rs];
}
#define ols ch[las][0]
#define ors ch[las][1]
void Merge(int &now,int las,int l,int r)
{
if(!now||!las) {now=las+now;return;}
if(l==r) {sum[now]+=sum[las];return;}
int mid=l+r>>1;
Merge(ls,ols,l,mid);
Merge(rs,ors,mid+1,r);
sum[now]=sum[ls]+sum[rs];
}
struct node
{
int i,k;
node(){}
node(int i,int k){this->i=i,this->k=k;}
}tt;
vector <node > ask[N];int ans[N];
int query(int now,int l,int r,int k)
{
if(l==r) return l;
int mid=l+r>>1;
if(sum[ls]>=k) return query(ls,l,mid,k);
else return query(rs,mid+1,r,k-sum[ls]);
}
void dfs(int now)
{
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(f[now][0]!=v)
{
dfs(v);
Merge(root[now],root[v],1,n);
}
}
for(int k,i=0;i<ask[now].size();i++)
{
k=ask[now][i].k;
ans[ask[now][i].i]=max(0,dep[now]-query(root[now],1,n,k));
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int u,v,i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
dep[1]=1;
dfs_(1);
for(int u,v,i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
int lca=LCA(u,v);
change(root[u],1,n,dep[lca]);
change(root[v],1,n,dep[lca]);
}
scanf("%d",&q);
for(int v,k,i=1;i<=q;i++)
{
scanf("%d%d",&v,&k);
tt=node(i,k);
ask[v].push_back(tt);
}
dfs(1);
for(int i=1;i<=q;i++)
printf("%d\n",ans[i]);
return 0;
}
2018.9.9
牛客 NOIp模拟1 T3 保护 解题报告的更多相关文章
- 牛客 NOIp模拟1 T1 中位数 解题报告
中位数 题目描述 小\(N\)得到了一个非常神奇的序列\(A\).这个序列长度为\(N\),下标从\(1\)开始.\(A\)的一个子区间对应一个序列,可以由数对\([l,r]\)表示,代表\(A[l] ...
- 牛客练习赛 小A与任务 解题报告
小A与任务 链接: https://ac.nowcoder.com/acm/contest/369/B 来源:牛客网 题目描述 小A手头有 \(n\) 份任务,他可以以任意顺序完成这些任务,只有完成当 ...
- 牛客OI周赛7-普及组 解题报告
出题人好评. 评测机差评. A 救救喵咪 二位偏序.如果数据范围大的话直接树状数组,不过才1000就\(O(n^2)\)暴力就ok了. #include <bits/stdc++.h> s ...
- nowcoder(牛客网)OI测试赛2 解题报告
qwq听说是一场普及组难度的比赛,所以我就兴高采烈地过来了qwq 然后发现题目确实不难qwq.....但是因为蒟蒻我太蒻了,考的还是很差啦qwq orz那些AK的dalao们qwq 赛后闲来无事,弄一 ...
- Solution -「牛客 NOIP 模拟赛」打拳
\(\mathcal{Description}\) 现 \(2^n\) 个人进行淘汰赛,他们的战力为 \(1\sim 2^n\),战力强者能战胜战力弱者,但是战力在集合 \(\{a_m\}\) 里 ...
- 牛客OI赛制测试赛3 解题报告
前话: 话说考试描述:普及难度. 于是想在这场比赛上涨点信心. 考出来的结果:Point:480 Rank:40 然而同机房的最好成绩是 510. 没考好啊!有点炸心态,D题一些细节没有注意, ...
- nowcoder(牛客网)OI测试赛3 解题报告
昨天因为胡搞了一会儿社团的事情,所以错过(逃过)了nowcoder的测试赛..... 以上,听说还是普及组难度qwq,而且还有很多大佬AK(然而我这么蒻肯定还是觉得有点难度的吧qwq) 不过我还是日常 ...
- NOIP模拟2017.6.11解题报告
T1: 水题: 代码: #include <cstdio> #include <iostream> #include <algorithm> using names ...
- NOIP模拟赛-旅行者问题 解题报告
旅行者问题 [问题描述] lahub是一个旅行者的粉丝,他想成为一个真正的旅行者,所以他计划开始一段旅行.lahub想去参观n个目的地(都在一条直道上).lahub在起点开始他的旅行.第i个目的地和起 ...
随机推荐
- 谈谈两种标准库类型---string和vector
两种最重要的标准库---string和vector string和vector是两种最重要的标准库类型,string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列. 一.标准库 ...
- LeetCode961 重复 N 次的元素
问题: 重复 N 次的元素 在大小为 2N 的数组 A 中有 N+1 个不同的元素,其中有一个元素重复了 N 次. 返回重复了 N 次的那个元素. 示例 1: 输入:[1,2,3,3] 输出:3 示例 ...
- Element-ui组件--pagination分页
一般写后台系统都会有很多的列表,有列表就相应的要用到分页,根据项目中写的几个分页写一下我对分页的理解,就当是学习笔记了. 这是Element-ui提供的完整的例子 <template> ...
- thymelef模板报错 the entity name must immediately follow the '&' in the entity reference
thymelef模板里面是不能实用&符号的 要用&转义符代替,官网也有文档说明可以用官方的通配符代替,官方文档http://www.thymeleaf.org/doc/tutorial ...
- Codeforces Round #462 (Div. 2) C DP
C. A Twisty Movement time limit per test 1 second memory limit per test 256 megabytes input standard ...
- https://www.cnblogs.com/gaoxiang12/p/3695962.html
https://www.cnblogs.com/gaoxiang12/p/3695962.html
- 笔记-redis安装
笔记-redis安装配置 1. redis安装配置 1.1. windows环境安装 win8已有redis 查看版本:redis-server –version 想更新到5.0.0, ...
- linux中如何解决克隆后的电脑的问题
1.如何解决克隆后的电脑的网络问题 克隆出来的电脑,IP地址,网卡都是重复的,不能直接使用,需要修改 1)vim /etc/udev/rules.d/70-persistent-net.rules ...
- javascript数组&省市联动分别用js数组和JSON实现
1.定义数组的三种方式: **数组可以存放不同的数据类型 第一种: var arr=[1,2,3]; var arr=[1,"2",true]; 第二种: 使用内置对象 ...
- Pycharm设置Python的路径
1. 打开文件->默认设置 2. 找到Python的路径即可,如果没有的话,这里也可以安装一个,只是时间比较久. 3. 选择本地 4. 选择文件