链接:https://www.nowcoder.com/acm/contest/172/C
来源:牛客网

题目描述

C国有n个城市,城市间通过一个树形结构形成一个连通图。城市编号为1到n,其中1号城市为首都。国家有m支军队,分别守卫一条路径的城市。具体来说,对于军队i,他守卫的城市区域可以由一对二元组(xi,yi)代表。表示对于所有在xi到yi的最短路径上的城市,军队i都会守卫他们。
现在有q个重要人物。对于一个重要人物j,他要从他的辖区vj出发,去到首都。出于某些原因,他希望找到一个离首都最近的,且在vj到首都路径上的城市uj,使得至少有kj支军队,能够全程保护他从vj到uj上所经过的所有城市。换句话说,至少有ki支军队,满足在树上,xi到yi的路径能完全覆盖掉vj到uj的路径。

输入描述:

第一行输入两个数n,m。
接下来n-1行,每行两个整数u,v,表示存在一条从城市u到城市v的道路。
接下来m行,每行两个整数x,y。描述一个军队的守卫区域。
接下来一行一个整数q。
接下来q行,每行两个整数vj,kj

输出描述:

对于每次询问,输出从v

j

到u

j

最少需要经过多少条边。假如不存在这样的u

j

,则输出0。
示例1

输入

复制

8 8
7 1
1 3
3 4
4 6
6 2
4 5
7 8
7 2
7 1
7 1
7 5
1 1
1 3
1 6
5 1
8
5 1
2 1
2 1
4 2
3 2
4 2
1 1
4 1

输出

复制

3
4
4
2
1
2
0
2

备注:

20%: n,m,q <= 300
40%: n,m,q <= 2000
60%: n,m,q <= 50000
100%: n,m,q <= 200000


题目给你一堆点对(X,Y),并且让你求出对于另外的给定点u,保证有k条路径完全覆盖(u,v)的v的最小深度。
我们考虑把(x,y)分为(x,p), (y,p), p为x和y的lca。
那么(u,v)被(x,y)覆盖其实就是(u,v)被(x,p)或者(y,p)覆盖。
这里我们只考虑被(x,p)覆盖。
那么肯定是x在u的子树中,p在v的子树之外。
我们对于每一个节点开一棵权值线段树,在x的线段树上的dep[p]位置+1,代表(x,p)有一条路径。
那么我们要(u,v)被(x,p)覆盖,只需要查询u的子树中的线段树是否有<=dep[v]的标记。
如果有那么就成立。
我们要找(u,v)被大于等于k条路径完全覆盖,很容易的想到区间第k小,我们只要在u的子树中的线段树上查询最小的k的存在标记的位置,就是v的深度。
此题完美解决。
(我太菜了考试的时候没想出来)。
所以重复一遍步骤 :
1.在每个节点开一棵权值线段树,然后对于每个(x,y)在x,y的线段树上分别在dep[lca(x,y)]的位置上+1.
2.dfs一遍合并一个节点儿子的所有子树的线段树。
3.对于每个询问,查询u的线段树中的第k小的位置记为e,答案就是dep[p]-e。


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define reg register
inline int read() {
int res = ;char ch=getchar();bool fu=;
while(!isdigit(ch)) {if(ch=='-')fu=;ch=getchar();}
while(isdigit(ch)) res=(res<<)+(res<<)+(ch^), ch=getchar();
return fu?-res:res;
}
#define N 200005
int n, m;
struct edge {
int nxt, to;
}ed[N*];
int head[N], cnt;
inline void add(int x, int y) {
ed[++cnt] = (edge){head[x], y};
head[x] = cnt;
} int dep[N];
int ff[N][];
inline void bfs()
{
dep[] = ;
dep[] = -;
queue <int> q;
q.push();
while(!q.empty())
{
int x = q.front();q.pop();
for (reg int i = head[x] ; i ; i = ed[i].nxt)
{
int to = ed[i].to;
if (dep[to]) continue;
dep[to] = dep[x] + ;
ff[to][] = x;
for (reg int j = ; j <= ; j ++)
ff[to][j] = ff[ff[to][j-]][j-];
q.push(to);
}
}
} inline int lca(int x, int y)
{
if (dep[x] < dep[y]) swap(x, y);
for (reg int i = ; i >= ; i --)
if (dep[ff[x][i]] >= dep[y]) x = ff[x][i];
if (x == y) return x;
for (reg int i = ; i >= ; i --)
if (ff[x][i] != ff[y][i]) x = ff[x][i], y = ff[y][i];
return ff[x][];
} int ls[N*], rs[N*], tr[N*], tot;
int root[N*]; int Insert(int l, int r, int o, int p)
{
if (!o) o = ++tot;
tr[o]++;
if (l == r) return o;
int mid = l + r >> ;
if (p <= mid) ls[o] = Insert(l, mid, ls[o], p);
else rs[o] = Insert(mid + , r, rs[o], p);
return o;
} int Merge(int l, int r, int a, int b)
{
if (a * b == ) return a + b;
int node = ++tot;
tr[node] = tr[a] + tr[b];
if (l == r) return node;
int mid = l + r >> ;
ls[node] = Merge(l, mid, ls[a], ls[b]);
rs[node] = Merge(mid + , r, rs[a], rs[b]);
return node;
} void dfs(int x, int fa)
{
for (reg int i = head[x] ; i ; i = ed[i].nxt)
{
int to = ed[i].to;
if (to == fa) continue;
dfs(to, x);
root[x] = Merge(, n, root[x], root[to]);
}
} int K_th(int l, int r, int o, int k)
{
if (tr[o] < k) return 1e9;
if (l == r) return l;
int mid = l + r >> ;
if (tr[ls[o]] >= k) return K_th(l, mid, ls[o], k);
else return K_th(mid + , r, rs[o], k - tr[ls[o]]);
} int main()
{
n = read(), m = read();
for (reg int i = ; i < n ; i ++)
{
int x = read(), y = read();
add(x, y), add(y, x);
}
bfs();
for (reg int i = ; i <= m ; i ++)
{
int x = read(), y = read();
int l = lca(x, y);
root[x] = Insert(, n, root[x], dep[l]);
root[y] = Insert(, n, root[y], dep[l]);
}
dfs(, );
int q = read();
while(q--)
{
int x = read(), k = read();
printf("%d\n", max(, dep[x] - K_th(, n, root[x], k)));
}
return ;
}

 

[牛客网NOIP赛前集训营-提高组(第一场)]C.保护的更多相关文章

  1. 牛客网NOIP赛前集训营-提高组(第四场)游记

    牛客网NOIP赛前集训营-提高组(第四场)游记 动态点分治 题目大意: \(T(t\le10000)\)组询问,求\([l,r]\)中\(k(l,r,k<2^{63})\)的非负整数次幂的数的个 ...

  2. 牛客网NOIP赛前集训营-提高组(第四场)B区间

    牛客网NOIP赛前集训营-提高组(第四场)B区间 题目描述 给出一个序列$ a_1  \dots   a_n$. 定义一个区间 \([l,r]\) 是好的,当且仅当这个区间中存在一个 \(i\),使得 ...

  3. 牛客网NOIP赛前集训营-提高组(第四场)B题 区间

    牛客网NOIP赛前集训营-提高组(第四场) 题目描述 给出一个序列 a1, ..., an. 定义一个区间 [l,r] 是好的,当且仅当这个区间中存在一个 i,使得 ai 恰好等于 al, al+1, ...

  4. 牛客网NOIP赛前集训营-普及组(第二场)和 牛客网NOIP赛前集训营-提高组(第二场)解题报告

    目录 牛客网NOIP赛前集训营-普及组(第二场) A 你好诶加币 B 最后一次 C 选择颜色 D 合法括号序列 牛客网NOIP赛前集训营-提高组(第二场) A 方差 B 分糖果 C 集合划分 牛客网N ...

  5. 牛客网NOIP赛前集训营-提高组18/9/9 A-中位数

    链接:https://www.nowcoder.com/acm/contest/172/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...

  6. 牛客网NOIP赛前集训营-提高组(第二场)A 方差

    链接:https://www.nowcoder.com/acm/contest/173/A来源:牛客网 题目描述 一个长度为 m 的序列 b[1...m] ,我们定义它的方差为 ,其中  表示序列的平 ...

  7. 牛客网NOIP赛前集训营-提高组(第八场)

    染色 链接:https://ac.nowcoder.com/acm/contest/176/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言10 ...

  8. 牛客网NOIP赛前集训营 提高组(第七场)

    中国式家长 2 链接:https://www.nowcoder.com/acm/contest/179/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K, ...

  9. 牛客网NOIP赛前集训营-提高组(第一场)

    牛客的这场比赛感觉真心不错!! 打得还是很过瘾的.水平也比较适合. T1:中位数: 题目描述 小N得到了一个非常神奇的序列A.这个序列长度为N,下标从1开始.A的一个子区间对应一个序列,可以由数对[l ...

随机推荐

  1. hive 元数据解析

    在使用Hive进行开发时,我们往往需要获得一个已存在hive表的建表语句(DDL),然而hive本身并没有提供这样一个工具. 要想还原建表DDL就必须从元数据入手,我们知道,hive的元数据并不存放在 ...

  2. Linux线程唤醒与等待

    生产者消费者模式在程序设计中出现频率非常高,经常会有线程间通过消息队列或其他共享变量进行交互的场景.而这时就会出现一个问题,消费者如何知道生产者已经生产了数据呢?有的程序会采取消费者循环判断消息队列大 ...

  3. servlet request、response的中文乱码问题

    一.request 1.get请求 get请求的参数是在请求行中的,浏览器使用utf-8进行编码,数据的编码一般为UTF-8,而url请求行的默认编码为ISO-8859-1,一般来说有以下方式可以解决 ...

  4. 【linux】【Fabric】Centos7搭建Fabric运行环境

    1.安装jdk1.8配置环境变量 参考:https://www.cnblogs.com/jxd283465/p/11541506.html 2.安装git yum -y install git 3.安 ...

  5. Node 与JS的区别

    1.nodejs是运行于服务器端的:2.global:代表node当中的一个全局对象,类似于浏览器当中的window,定义全局对象:global.a:3.作用域:nodejs中一个文件就是一个作用域: ...

  6. MyEclipse 中无法直接使用BaseEncoder问题

    首先 :点击项目---->build path--->configure Build Path 然后:java build path --->libraries--->JRE ...

  7. Spring 梳理 - WebMvcConfigurerAdapter详解

    参考:https://blog.csdn.net/weixin_43453386/article/details/83623242

  8. Spring Cloud Stream 整合 RabbitMQ

    简介 Spring Cloud Stream是一个构建消息驱动微服务的框架,应用程序通过input(相当于consumer).output(相当于producer)来与Spring Cloud Str ...

  9. C#2匿名方法中的捕获变量

    乍一接触"匿名方法中的捕获变量"这一术语可能会优点蒙,那什么是"匿名方法中的捕获变量"呢?在章节未开始之前,我们先定义一个委托:public delegate  ...

  10. 系统定时任务crond

    1.Linux的定时任务:crond(crontab)服务 (1)crond 是什么? crond 是 linux 系统中用来定期执行命令或者指定程序任务的一种服务和软件:crond 服务默认情况(每 ...