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. SSH电力项目二

    底层方法封装(CommonDaoImpl类) public class CommonDaoImpl<T> extends HibernateDaoSupport implements IC ...

  2. 【面向对象】----【prototype&&__proto__&&实例化对象三者之间的关系】(四)-----【巷子】

    1.构造函数 a.什么是构造函数? 解释:通过关键字new 创建的函数叫做构造函数 作用:用来创建一个对象 废话少说直接上代码,首先我们还是创建一个构造函数人类 然后我们在创建两个实例,一个凡尘 一个 ...

  3. SaltStack配置管理-jinja模板

    上一篇:SaltStack配置管理-状态间关系 需求:需要apache配置文件里面监听的端口是每个minion本地的地址 saltstack默认的模板是jinjia模板 参考文档:http://doc ...

  4. HDU 6016 Count the Sheep

    Count the Sheep Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  5. Python+ Calibre 处理 中文报纸

    import re ##2 line='<a href=nw.D110000renmrb_20180401_1-01.htm><script>document.write(vi ...

  6. Finding files on a *nix/Linux and sorting by size

    1. Finding files on *NIX and sort by size find ~ -iregex ".*/*.sh" -type f -print0 | xargs ...

  7. SprinBoot CLI 安装(Mac版)

    1. 安装 HomeBrew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/instal ...

  8. Key Set---hud5363(快速幂)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5363 #include <iostream> #include <cstdlib&g ...

  9. postman app支持浏览器上的cookie

    1.  安装postman app 注意要安装postman application(一个应用软件),而不是chrome 插件,打开下面的这个开关 2. chrom浏览器 给chrom浏览器安装pos ...

  10. modelform动态显示select标签的对象范围

    既根据当前登录人,动态显示对象相关的的select的选项,例如 A登录,只显示A的客户,B登录,只显示B自己的客户 先了解form的ModelChoiceField字段(这个表格没意义,就是引出参数q ...