zoukankan      html  css  js  c++  java
  • Gym

    题意:给出棵树上的k条路径,求这些路径的公共点数量。

    将每条路径上的点都打上标记,被标记过k次的点就是公共点了。由于公共点形成的区间是连续的,因此直接在线段树上暴搜即可在$O(logn)$求出一条链上公共点的数量。

    怎样找被标记过k次的点呢?可以维护一个区间最大值mx和一个区间最小值mi,如果mx=mi=k说明这一段区间上的点全都为公共点。

    清除标记加个线段树区间赋值即可(也可以把标记过的路径一条一条去掉)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e4+10,mod=1e9+7;
     5 int hd[N],n,ne,Q,m,fa[N],son[N],siz[N],dep[N],top[N],dfn[N],rnk[N],tot,ka;
     6 int mx[N<<2],mi[N<<2],lza[N<<2],lzs[N<<2];
     7 struct E {int v,nxt;} e[N<<1];
     8 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
     9 void dfs1(int u,int f,int d) {
    10     fa[u]=f,son[u]=0,siz[u]=1,dep[u]=d;
    11     for(int i=hd[u]; ~i; i=e[i].nxt) {
    12         int v=e[i].v;
    13         if(v==fa[u])continue;
    14         dfs1(v,u,d+1),siz[u]+=siz[v];
    15         if(siz[v]>siz[son[u]])son[u]=v;
    16     }
    17 }
    18 void dfs2(int u,int tp) {
    19     top[u]=tp,dfn[u]=++tot,rnk[dfn[u]]=u;
    20     if(son[u])dfs2(son[u],top[u]);
    21     for(int i=hd[u]; ~i; i=e[i].nxt) {
    22         int v=e[i].v;
    23         if(v==fa[u]||v==son[u])continue;
    24         dfs2(v,v);
    25     }
    26 }
    27 #define ls (u<<1)
    28 #define rs (u<<1|1)
    29 #define mid ((l+r)>>1)
    30 void pu(int u) {mx[u]=max(mx[ls],mx[rs]),mi[u]=min(mi[ls],mi[rs]);}
    31 void change(int u,int x,int f) {
    32     if(f==0)lza[u]=0,lzs[u]=mx[u]=mi[u]=x;
    33     else lza[u]+=x,mx[u]+=x,mi[u]+=x;
    34 }
    35 void pd(int u) {
    36     if(~lzs[u])change(ls,lzs[u],0),change(rs,lzs[u],0),lzs[u]=-1;
    37     if(lza[u])change(ls,lza[u],1),change(rs,lza[u],1),lza[u]=0;
    38 }
    39 void upd(int L,int R,int x,int f,int u=1,int l=1,int r=tot) {
    40     if(l>=L&&r<=R) {change(u,x,f); return;}
    41     if(l>R||r<L)return;
    42     pd(u),upd(L,R,x,f,ls,l,mid),upd(L,R,x,f,rs,mid+1,r),pu(u);
    43 }
    44 int qry(int L,int R,int u=1,int l=1,int r=tot) {
    45     if(l>=L&&r<=R&&mx[u]==m&&mi[u]==m)return r-l+1;
    46     if(l>R||r<L||mx[u]!=m)return 0;
    47     pd(u);
    48     return qry(L,R,ls,l,mid)+qry(L,R,rs,mid+1,r);
    49 }
    50 void upd2(int u,int v) {
    51     for(; top[u]!=top[v]; u=fa[top[u]]) {
    52         if(dep[top[u]]<dep[top[v]])swap(u,v);
    53         upd(dfn[top[u]],dfn[u],1,1);
    54     }
    55     if(dep[u]<dep[v])swap(u,v);
    56     upd(dfn[v],dfn[u],1,1);
    57 }
    58 int qry2(int u,int v) {
    59     int ret=0;
    60     for(; top[u]!=top[v]; u=fa[top[u]]) {
    61         if(dep[top[u]]<dep[top[v]])swap(u,v);
    62         ret+=qry(dfn[top[u]],dfn[u]);
    63     }
    64     if(dep[u]<dep[v])swap(u,v);
    65     ret+=qry(dfn[v],dfn[u]);
    66     return ret;
    67 }
    68 int main() {
    69     int T;
    70     for(scanf("%d",&T); T--;) {
    71         printf("Case %d:
    ",++ka);
    72         memset(hd,-1,sizeof hd),ne=tot=0;
    73         scanf("%d",&n);
    74         for(int i=1; i<n; ++i) {
    75             int u,v;
    76             scanf("%d%d",&u,&v);
    77             addedge(u,v);
    78             addedge(v,u);
    79         }
    80         dfs1(1,0,1),dfs2(1,1);
    81         scanf("%d",&Q);
    82         while(Q--) {
    83             upd(1,tot,0,0);
    84             scanf("%d",&m);
    85             for(int i=0; i<m; ++i) {
    86                 int u,v;
    87                 scanf("%d%d",&u,&v);
    88                 upd2(u,v);
    89                 if(i==m-1)printf("%d
    ",qry2(u,v));
    90             }
    91         }
    92     }
    93 }
  • 相关阅读:
    java 读取src下的配置文件
    图书管理系统
    StaticDemo
    MatixDemo
    Magics
    GetPrime
    ConWithThis
    TestTHIS
    ConstructorOverLoad
    Sequence
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11342895.html
Copyright © 2011-2022 走看看