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的路径。
 
貌似主席树维护$DFS$序这种题目用线段树合并都可以搞,好像本质上都是按照$DFS$序建树
首先把一条覆盖路径拆成两点到$LCA$的两条路径(套路)
然后我们二分这个最小深度,可以发现,如果子树内的路径端点大于二分深度的个数大于等于$k$,那么该深度就合法
然后子树的的信息显然可以用线段树合并维护,二分过程也可以用线段树二分实现
总复杂度$(nlogn)$
代码:
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define M 200010
#define ls ch[node][0]
#define rs ch[node][1]
using namespace std;
vector<int>S[M],Q[M];
int n,m,num,cnt,q;
int head[M],deep[M],ans[M],a[M],f[M],sz[M],son[M],top[M],rt[M];
int val[M<<],ch[M<<][];
struct point{int to,next;}e[M<<];
void add(int from,int to) {
e[++num].next=head[from];
e[num].to=to;
head[from]=num;
}
void dfs1(int x) {
deep[x]=deep[f[x]]+,sz[x]=;
for(int i=head[x];i;i=e[i].next) {
int to=e[i].to;
if(to==f[x]) continue;
f[to]=x;dfs1(to),sz[x]+=sz[to];
if(sz[son[x]]<sz[to]) son[x]=to;
}
}
void dfs2(int x,int tp) {
top[x]=tp;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=f[x]&&e[i].to!=son[x])
dfs2(e[i].to,e[i].to);
}
int lca(int x,int y) {
while(top[x]!=top[y]) {
if(deep[top[x]]<deep[top[y]]) swap(x,y);
x=f[top[x]];
}
return deep[x]<deep[y]?x:y;
}
void insert(int &node,int l,int r,int x,int v) {
if(!node) node=++cnt;val[node]+=v;
if(l==r) return;
int mid=(l+r)/;
if(x<=mid) insert(ls,l,mid,x,v);
else insert(rs,mid+,r,x,v);
}
int query(int node,int l,int r,int d) {
if(val[node]<d) return -;
if(l==r) return l;
int mid=(l+r)/;
if(d<=val[ls]) return query(ls,l,mid,d);
else return query(rs,mid+,r,d-val[ls]);
}
int merge(int x,int y,int l,int r) {
if(!x||!y) return x+y;
int node=++cnt;
if(l==r) {
val[node]=val[x]+val[y];
return node;
}
int mid=(l+r)/;
ls=merge(ch[x][],ch[y][],l,mid);
rs=merge(ch[x][],ch[y][],mid+,r);
val[node]=val[ls]+val[rs];
return node;
}
void dfs(int x,int fa) {
for(int i=;i<S[x].size();i++)
insert(rt[x],,n,S[x][i],);
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=fa)
dfs(e[i].to,x);
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=fa)
rt[x]=merge(rt[x],rt[e[i].to],,n);
for(int i=;i<Q[x].size();i++) {
int id=Q[x][i],u=a[id];
int res=query(rt[x],,n,u);
if(res==-||res>deep[x]) ans[id]=;
else ans[id]=deep[x]-res;
}
}
int main() {
scanf("%d%d",&n,&m);
for(int i=;i<n;i++) {
int x,y;scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
dfs1(),dfs2(,);
for(int i=;i<=m;i++) {
int x,y;scanf("%d%d",&x,&y);
int LCA=lca(x,y);
if(x!=LCA) S[x].push_back(deep[LCA]);
if(y!=LCA) S[y].push_back(deep[LCA]);
}
scanf("%d",&q);
for(int i=;i<=q;i++) {
int x,y;scanf("%d%d",&x,&y);
a[i]=y;Q[x].push_back(i);
}
dfs(,);
for(int i=;i<=q;i++) printf("%d\n",ans[i]);
return ;
}

[nowcoder]contest/172/C保护的更多相关文章

  1. 「NowCoder Contest 295」H. Playing games

    还是见的题太少了 「NowCoder Contest 295」H. Playing games 题意:选出尽量多的数使得异或和为$ 0$ $ Solution:$ 问题等价于选出尽量少的数使得异或和为 ...

  2. AtCoder Beginner Contest 172 题解

    AtCoder Beginner Contest 172 题解 目录 AtCoder Beginner Contest 172 题解 A - Calc B - Minor Change C - Tsu ...

  3. Nowcoder contest 370B Rinne Loves Graph 【分层图最短路】

    <题目链接> 题目大意: Island 是有一些奇怪的城镇和道路构成的(题目需要,游戏党勿喷),有些城镇之间用双向道路连接起来了,且每条道路有它自己的距离.但是有一些城镇已经被派兵戒严,虽 ...

  4. Nowcoder contest 370H Rinne Loves Dynamic Graph【分层图最短路】

    <题目链接> 题目大意:Rinne 学到了一个新的奇妙的东西叫做动态图,这里的动态图的定义是边权可以随着操作而变动的图.当我们在这个图上经过一条边的时候,这个图上所有边的边权都会发生变动. ...

  5. Nowcoder contest 370F Rinne Loves Edges (简单树形DP) || 【最大流】(模板)

    <题目链接> 题目大意: 一个 $n$ 个节点 $m$ 条边的无向连通图,每条边有一个边权 $w_i$.现在她想玩一个游戏:选取一个 “重要点” S,然后选择性删除一些边,使得原图中所有除 ...

  6. Nowcoder contest 392 I 逛公园 (无向图割边模板)

    <题目链接> 题目描述: 月月和华华一起去逛公园了.公园很大,为了方便,可以抽象的看成一个N个点M条边的无向连通图(点是景点,边是道路).公园唯一的入口在1号点,月月和华华要从这里出发,并 ...

  7. [ Nowcoder Contest 175 #B ] 区间

    \(\\\) \(Description\) 给出一个长度为\(N\)的序列\(A[1]...A[N]\),定义一个合法区间 \([L,R]\) 当且仅当区间\(GCD\) 在这个区间内,求最长合法区 ...

  8. [ Nowcoder Contest 167 #D ] 重蹈覆辙

    \(\\\) \(Description\) 用\(1\times 2\)的矩形和面积为\(3\)的\(L\)形去覆盖一个\(2\times N\) 的矩形,求方案数对\(10^4+7\)取模后的结果 ...

  9. [ Nowcoder Contest 167 #C ] 部分和

    \(\\\) \(Description\) 给出一个长度为\(N\)的数组\(A[i]\),保证\(N\)为 \(2\) 的整次幂. 对于每个 \(i\ (i\in [0,N))\)求所有满足\(( ...

随机推荐

  1. 标准web浏览器的组件

    浏览器基本上包括如下几个组件 1.HTML.XML.CSS.JavsScript解析器 2.Layout 3.文字和图形渲染 4.图像解码 5.GPU交互 6.网络访问 7.硬件加速

  2. ios 自定义NavgationBar的按钮

    UIImage *btnimage = [UIImage imageNamed:@"about.png"]; UIButton *btn = [[UIButton alloc] i ...

  3. dubbo用途介绍

    转自:http://blog.csdn.net/wuliu_forever/article/details/52053928 我们讨论过Nginx+tomcat组成的集群,这已经是非常灵活的集群技术, ...

  4. Spark集群安装和WordCount编写

    一.Spark概述 官网:http://spark.apache.org/ Apache Spark™是用于大规模数据处理的统一分析引擎. 为大数据处理而设计的快速通用的计算引擎. Spark加州大学 ...

  5. Python开发【Django】:Model操作(二)

    Model操作 1.操作汇总: # 增 # # models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs # obj ...

  6. 修改hosts搭建本地站点

    想要搭建本地站点.例如想要将www.nbb.com映射到本地服务器,而不是网络的.需要修改hosts文件 1 打开hosts所在目录  C:\Windows\System32\drivers\etc ...

  7. tomcat启动错误:ZipException

    [/opt/apache-tomcat-/webapps/secsight.war] -Dec- ::] org.apache.catalina.core.ContainerBase.addChild ...

  8. qt——exec()的基本用法

    qt中 if(my1.exec()==QDialog::Accepted) 是什么意思 这个先说这个my1.exec()这个就是个等待消息的循环,就是说它在等待你给的命令. 再说这个QDialog:: ...

  9. 产品开发过程描述xmind

  10. 【剑指Offer】俯视50题之1-10题

    面试题1赋值运算符函数  面试题2 实现Singleton模式  面试题3 二维数组中的查找   面试题4 替换空格   面试题5 从头到尾打印链表   面试题6 重建二叉树   面试题7 用两个栈实 ...