zoukankan      html  css  js  c++  java
  • [nowcoder]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的路径。
     
    貌似主席树维护$DFS$序这种题目用线段树合并都可以搞,好像本质上都是按照$DFS$序建树
    首先把一条覆盖路径拆成两点到$LCA$的两条路径(套路)
    然后我们二分这个最小深度,可以发现,如果子树内的路径端点大于二分深度的个数大于等于$k$,那么该深度就合法
    然后子树的的信息显然可以用线段树合并维护,二分过程也可以用线段树二分实现
    总复杂度$(nlogn)$
    代码:
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<vector>
      5 #define M 200010
      6 #define ls ch[node][0]
      7 #define rs ch[node][1]
      8 using namespace std;
      9 vector<int>S[M],Q[M];
     10 int n,m,num,cnt,q;
     11 int head[M],deep[M],ans[M],a[M],f[M],sz[M],son[M],top[M],rt[M];
     12 int val[M<<8],ch[M<<8][2];
     13 struct point{int to,next;}e[M<<1];
     14 void add(int from,int to) {
     15     e[++num].next=head[from];
     16     e[num].to=to;
     17     head[from]=num;
     18 }
     19 void dfs1(int x) {
     20     deep[x]=deep[f[x]]+1,sz[x]=1;
     21     for(int i=head[x];i;i=e[i].next) {
     22         int to=e[i].to;
     23         if(to==f[x]) continue;
     24         f[to]=x;dfs1(to),sz[x]+=sz[to];
     25         if(sz[son[x]]<sz[to]) son[x]=to;
     26     }
     27 }
     28 void dfs2(int x,int tp) {
     29     top[x]=tp;
     30     if(son[x]) dfs2(son[x],tp);
     31     for(int i=head[x];i;i=e[i].next)
     32         if(e[i].to!=f[x]&&e[i].to!=son[x])
     33             dfs2(e[i].to,e[i].to);
     34 }
     35 int lca(int x,int y) {
     36     while(top[x]!=top[y]) {
     37         if(deep[top[x]]<deep[top[y]]) swap(x,y);
     38         x=f[top[x]];
     39     }
     40     return deep[x]<deep[y]?x:y;
     41 }
     42 void insert(int &node,int l,int r,int x,int v) {
     43     if(!node) node=++cnt;val[node]+=v;
     44     if(l==r) return;
     45     int mid=(l+r)/2;
     46     if(x<=mid) insert(ls,l,mid,x,v);
     47     else insert(rs,mid+1,r,x,v);
     48 }
     49 int query(int node,int l,int r,int d) {
     50     if(val[node]<d) return -1;
     51     if(l==r) return l;
     52     int mid=(l+r)/2;
     53     if(d<=val[ls]) return query(ls,l,mid,d);
     54     else return query(rs,mid+1,r,d-val[ls]);
     55 }
     56 int merge(int x,int y,int l,int r) {
     57     if(!x||!y) return x+y;
     58     int node=++cnt;
     59     if(l==r) {
     60         val[node]=val[x]+val[y];
     61         return node;
     62     }
     63     int mid=(l+r)/2;
     64     ls=merge(ch[x][0],ch[y][0],l,mid);
     65     rs=merge(ch[x][1],ch[y][1],mid+1,r);
     66     val[node]=val[ls]+val[rs];
     67     return node;
     68 }
     69 void dfs(int x,int fa) {
     70     for(int i=0;i<S[x].size();i++)
     71         insert(rt[x],1,n,S[x][i],1);
     72     for(int i=head[x];i;i=e[i].next)
     73         if(e[i].to!=fa)
     74             dfs(e[i].to,x);
     75     for(int i=head[x];i;i=e[i].next)
     76         if(e[i].to!=fa)
     77             rt[x]=merge(rt[x],rt[e[i].to],1,n);
     78     for(int i=0;i<Q[x].size();i++) {
     79         int id=Q[x][i],u=a[id];
     80         int res=query(rt[x],1,n,u);
     81         if(res==-1||res>deep[x]) ans[id]=0;
     82         else ans[id]=deep[x]-res;
     83     }
     84 }
     85 int main() {
     86     scanf("%d%d",&n,&m);
     87     for(int i=1;i<n;i++) {
     88         int x,y;scanf("%d%d",&x,&y);
     89         add(x,y),add(y,x);
     90     }
     91     dfs1(1),dfs2(1,1);
     92     for(int i=1;i<=m;i++) {
     93         int x,y;scanf("%d%d",&x,&y);
     94         int LCA=lca(x,y);
     95         if(x!=LCA) S[x].push_back(deep[LCA]);
     96         if(y!=LCA) S[y].push_back(deep[LCA]);
     97     }
     98     scanf("%d",&q);
     99     for(int i=1;i<=q;i++) {
    100         int x,y;scanf("%d%d",&x,&y);
    101         a[i]=y;Q[x].push_back(i);
    102     }
    103     dfs(1,0);
    104     for(int i=1;i<=q;i++) printf("%d
    ",ans[i]);
    105     return 0;
    106 }
  • 相关阅读:
    Dynamics 365 多租户?多实例?
    接口接收gzip压缩数据并解压
    系统检测到在一个调用中尝试使用指针参数时的无效指针地址 问题
    PBI DAX 中GroupBy
    将sql 查询结果导出到excel
    自动生成数据库表分区脚本
    快速生成导入亿级测试数据到sqlserver
    powershell 版本问题
    运行powershell 脚本 在此系统上禁止运行脚本
    python网站收集
  • 原文地址:https://www.cnblogs.com/Slrslr/p/10060247.html
Copyright © 2011-2022 走看看