牛客 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个目的地和起 ...
随机推荐
- FAT32中文版分析+补充(1)
概述 起先所有的FAT文件系统都是为IBM PC机器而设计的,这说明了一个重要的问题:FAT文件系统在磁盘上的数据是用“小端”(Little Endian)结构存储的.我们使用4个8-bit的字节—— ...
- Hibernate基础学习2
Hibernate基础学习2 测试hibernate的一级缓存,事务以及查询语句 1)Hibernate的一些相关概念 hibernate的一级缓存 1)缓存是为了提高该框架对数据库的查询速度 2)一 ...
- 无法打开物理文件 XXX.mdf“,操作系统错误 5:”5(拒绝访问。)"的解决办法
http://blog.csdn.net/blackfield/article/details/6550499 用T-SQL命令附加数据库时,出现如下异常信息: 无法打开物理文件 XXX.mdf&qu ...
- 改进的平台设备驱动——dev和drv完全分离
这是平台设备: 1 #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> # ...
- Windows手工创建服务方法
需要将程序设置成Windows服务的情况,可以利用一下windows自带的sc命令来创建服务. 该命令的基本用法如下:打开cmd命令, 输入如下信息:1 创建服务:sc create SecServe ...
- 8 Django 模型层(1)--orm简介
ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的 ...
- 3437: 小P的牧场
3437: 小P的牧场 思路 斜率优化. dp[i]表示到第i个点(第i个点按控制台)的最小代价. 代码 #include<cstdio> #include<iostream> ...
- springboot遇见问题总结
今天开始学习创建springboot项目 问题1: 产生异常: 创建项目目录: demo代码: 代码Controller import org.springframework.web.bind.ann ...
- linux中jdk的安装与mysql 的安装
1.linux安装jdk #先找到 安装包#cd /usr/java tar -zxvf jdk-8u31-linux-x64.tar.gz 2.安装选择要安装java的位置,如/usr/目录下,新建 ...
- Visual Studio 2017 的 JavaScript 调试功能的关闭
关闭方法其实很简单,Options => Debugging => General => Enable JavaScript debugging for ASP.NET (Chrom ...