• Wannafly挑战赛1 C MMSet2


    题目链接:Wannafly挑战赛1 C MMSet2

    题意:

    中文不解释。

    题解:

    比赛的时候是用的lca+贪心。

    今天学了学虚树,这题实际就是求一个虚树的直径。

      1 #include<bits/stdc++.h>
      2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
      3 #define mst(a,b) memset(a,b,sizeof(a))
      4 using namespace std;
      5 typedef pair<int,int>P;
      6 
      7 const int N=3e5+7;
      8 int in[N],out[N],ti,Dep[N];
      9 namespace LCA
     10 {
     11     int g[N],v[N*2],nxt[N*2],ed,f[20][N*2];
     12     int idx[N],dep[N*2],vs[N*2],dfn;
     13     void init(int n){ed=0,dfn=1;F(i,0,n)g[i]=0;}
     14     void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
     15     void dfs(int u=1,int fa=0,int d=0)
     16     {
     17         in[u]=++ti,Dep[u]=d;
     18         idx[u]=dfn,vs[dfn]=u,dep[dfn++]=d;
     19         for(int i=g[u];i;i=nxt[i])if(v[i]!=fa)
     20         dfs(v[i],u,d+1),vs[dfn]=u,dep[dfn++]=d;
     21         out[u]=ti;
     22     }
     23     void lca_init(int rt)
     24     {
     25         dfs(rt);F(i,1,dfn-1)f[0][i]=i;
     26         for(int i=1;(1<<i)<dfn;++i)
     27             for(int j=1;j+(1<<i)-1<dfn;++j)
     28             {
     29                 int a=f[i-1][j],b=f[i-1][j+(1<<(i-1))];
     30                 f[i][j]=dep[a]<=dep[b]?a:b;
     31             }
     32     }
     33     int lca(int x,int y)
     34     {
     35         x=idx[x],y=idx[y];
     36         if(x>y)x^=y,y^=x,x^=y;
     37         int k=31-__builtin_clz(y-x+1);
     38         int a=f[k][x],b=f[k][y-(1<<k)+1];
     39         return vs[dep[a]<=dep[b]?a:b];
     40     }
     41 }
     42 
     43 
     44 namespace vtree
     45 {
     46     int q[N],t,tot,x;bool vis[N],vip[N];vector<P>G[N];
     47     void clear(int *a,int tot){F(i,1,tot)vis[a[i]]=vip[a[i]]=0,G[a[i]].clear();}
     48     bool cmp(int x,int y){return in[x]<in[y];}
     49     void addedge(int x,int y)
     50     {
     51         G[x].push_back(P(y,Dep[y]-Dep[x]));
     52         G[y].push_back(P(x,Dep[y]-Dep[x]));
     53     }
     54     //构建m个点的虚树,用完记得clear(a,tot),注意特判1号节点。
     55     int build(int *a,int m)
     56     {
     57         F(i,1,m)vis[a[i]]=vip[a[i]]=1;
     58         if(!vis[1])a[++m]=1;
     59         sort(a+1,a+1+m,cmp),tot=m;
     60         F(i,2,m)if((x=LCA::lca(a[i-1],a[i]))!=1&&!vis[x])vis[a[++tot]=x]=1;
     61         sort(a+1,a+1+tot,cmp),q[t=1]=1;
     62         F(i,2,tot)
     63         {
     64             while(in[a[i]]<in[q[t]]||out[a[i]]>out[q[t]])t--;
     65             addedge(q[t],a[i]),q[++t]=a[i];
     66         }
     67         return tot;
     68     }
     69 }
     70 
     71 int n,m,x,y,num,a[N],mx[N];
     72 
     73 void dfs(int x,int fa,int val)
     74 {
     75     mx[x]=val;
     76     for(auto &it:vtree::G[x])
     77         if(it.first!=fa)
     78             dfs(it.first,x,val+it.second);
     79 }
     80 
     81 int main(){
     82     scanf("%d",&n);
     83     F(i,2,n)
     84     {
     85         scanf("%d%d",&x,&y);
     86         LCA::adg(x,y),LCA::adg(y,x);
     87     }
     88     LCA::lca_init(1),scanf("%d",&m);
     89     F(i,1,m)
     90     {
     91         scanf("%d",&num);
     92         F(j,1,num)scanf("%d",a+j);
     93         num=vtree::build(a,num);
     94         dfs(1,0,0);
     95         int now,v=-1;
     96         F(j,1,num)if(mx[a[j]]>v)now=a[j],v=mx[a[j]];
     97         dfs(now,0,0),v=-1;
     98         F(j,1,num)if(vtree::vis[a[j]])
     99         {
    100             if(mx[a[j]]>v)v=mx[a[j]];
    101         }
    102         printf("%d
    ",(v+1)/2);
    103         vtree::clear(a,num);
    104     }
    105     return 0;
    106 }
    View Code
  • 相关阅读:
    Spark Application的调度算法
    spark 问题
    读取hdfs文件之后repartition 避免数据倾斜
    生成树
    Curator Cache
    Curator leader 选举(一)
    Spark ZooKeeper数据恢复
    Curator 异步获取结果
    spark shuffle 相关细节整理
    matlab 求解线性方程组之LU分解
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7725596.html
Copyright © 2020-2023  润新知