zoukankan      html  css  js  c++  java
  • bzoj3572[Hnoi2014]世界树

    http://www.lydsy.com/JudgeOnline/problem.php?id=3572

    首先我们先构建出虚树

    然后在虚树上DP,求出虚树上每个点离最近的临时议事处在哪里

    对于虚树上相邻的两个点$u$和$v$,他们连线上一定存在一个分界处,一边一定会去离$u$最近的临时议事处;另一边一定会去离$v$最近的临时议事处

    然后就做完了

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<vector>
    #include<functional>
    #include<deque>
    #include<cctype>
    #include<climits>
    #include<complex>
    #include<cassert> 
    //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
     
    using namespace std;
    
    typedef long long LL;
    typedef double DB;
    typedef pair<int,int> PII;
    typedef pair<DB,DB> PDD;
    typedef complex<DB> CP;
    typedef vector<int> VI;
    
    #define mmst(a,v) memset(a,v,sizeof(a))
    #define mmcy(a,b) memcpy(a,b,sizeof(a))
    #define fill(a,l,r,v) fill(a+l,a+r+1,v)
    #define re(i,a,b)  for(i=(a);i<=(b);i++)
    #define red(i,a,b) for(i=(a);i>=(b);i--)
    #define fi first
    #define se second
    #define mp(a,b) make_pair(a,b)
    #define pb(a) push_back(a)
    #define SF scanf
    #define PF printf
    #define two(k) (1<<(k))
    #define SZ(x) (int(x.size()))
    #define all(x) (x).begin(),(x).end()
    #define ire(i,v,x) for(i=0,v=i<SZ(x)?x[i]:0;i<SZ(x);v=x[++i])
    
    
    template<class T>inline T sqr(T x){return x*x;}
    template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
    template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}
    
    inline int sgn(DB x){if(abs(x)<1e-9)return 0;return(x>0)?1:-1;}
    const DB Pi=acos(-1.0);
    
    int gint()
      {
            int res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    LL gll()
      {
          LL res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    
    const int maxn=300100;
    
    int n;
    VI e[maxn];
    
    const int up=25;
    int dep[maxn],jump[maxn][up+1];
    int head,tail,que[maxn];
    int sz[maxn],idx[maxn];
    void  bfs()
      {
          int i,j;
          dep[que[head=tail=1]=1]=1;
          re(j,0,up)jump[1][j]=1;
          while(head<=tail)
            {
                int u=que[head++];
                re(i,0,SZ(e[u])-1)if(!dep[e[u][i]])
                  {
                      int v=e[u][i];
                      dep[que[++tail]=v]=dep[u]+1;
                      jump[v][0]=u;
                      re(j,1,up)jump[v][j]=jump[jump[v][j-1]][j-1];
                  }
            }
          red(i,tail,1)
            {
                int u=que[i];
                sz[u]=1;
                re(j,0,SZ(e[u])-1)if(dep[e[u][j]]>dep[u])sz[u]+=sz[e[u][j]];
            }
          idx[1]=1;
          re(i,1,tail)
            {
                int u=que[i],tmp=0;
                re(j,0,SZ(e[u])-1)if(dep[e[u][j]]>dep[u]){int v=e[u][j];idx[v]=idx[u]+tmp+1,tmp+=sz[v];}
            }
      }
    
    int swim(int x,int H){for(int i=0;H;H>>=1,i++)if(H&1)x=jump[x][i];return x;}
    int ask_lca(int x,int y)
      {
          if(dep[x]<dep[y])swap(x,y);
          x=swim(x,dep[x]-dep[y]);
          if(x==y)return x;
          int i;red(i,up,0)if(jump[x][i]!=jump[y][i])x=jump[x][i],y=jump[y][i];
          return jump[x][0];
      }
    
    int m,h[maxn],h2[maxn];
    int mark[maxn],ans[maxn];
    VI to[maxn];
    int ge,w[maxn];
    
    bool cmp(int a,int b){return idx[a]<idx[b];}
    
    int top,sta[maxn];
    void addedge(int u,int v){to[u].pb(v);to[v].pb(u);}
    void build()
      {
          int i;
          re(i,1,ge)to[w[i]].clear();
          sort(h+1,h+m+1,cmp);
          ge=0;
          sta[top=1]=1;
          re(i,2,m)
            {
                while(1)
                  {
                      int lca=ask_lca(h[i],sta[top]);
                      if(lca==sta[top])break;
                      if(idx[lca]>idx[sta[top-1]])
                        {
                            w[++ge]=sta[top];
                            addedge(sta[top],lca);
                            sta[top]=lca;
                        }
                      else
                        {
                            addedge(sta[top],sta[top-1]);
                            w[++ge]=sta[top--];
                        }
                  }
                sta[++top]=h[i];
            }
          while(top>=2)addedge(sta[top],sta[top-1]),w[++ge]=sta[top--];
          w[++ge]=sta[top--];
      }
    
    const int inf=0x3f3f3f3f;
    PII f[maxn];
    int fa[maxn];
    void solve()
      {
          int i,j;
          re(i,1,ge)fa[w[i]]=0,f[w[i]]=mark[w[i]]?mp(0,w[i]):mp(inf,0);
          que[head=tail=1]=1;
          while(head<=tail)
            {
                int u=que[head++];
                re(j,0,SZ(to[u])-1)if(to[u][j]!=fa[u])fa[que[++tail]=to[u][j]]=u;
            }
          red(i,tail,2)
            {
                int u=que[i],v=fa[u];
                upmin(f[v],mp(f[u].fi+dep[u]-dep[v],f[u].se));
            }
          re(i,2,tail)
            {
                int u=que[i],v=fa[u];
                upmin(f[u],mp(f[v].fi+dep[u]-dep[v],f[v].se));
            }
          re(i,1,tail)
            {
                int x=que[i],tmp=sz[x];
                re(j,0,SZ(to[x])-1)if(to[x][j]!=fa[x])
                      {
                          int y=to[x][j],z=swim(y,dep[y]-dep[x]-1);
                            tmp-=sz[z];
                        }
                    ans[f[x].se]+=tmp;
            }
          re(i,2,tail)
            {
                int x=que[i],y=fa[x],dist=dep[x]-dep[y],z=swim(x,dist-1);
                if(f[x].se==f[y].se)
                  ans[f[x].se]+=sz[z]-sz[x];
                else
                  {
                      int d=(f[y].fi-f[x].fi+dist)/2.0;
                      if((f[y].fi-f[x].fi+dist)%2==0 && f[y].se<f[x].se)d--;
                      int u=swim(x,d);
                      ans[f[y].se]+=sz[z]-sz[u];
                      ans[f[x].se]+=sz[u]-sz[x];
                  }
            }
      }
    
    int main()
      {
          freopen("worldtree.in","r",stdin);
            freopen("worldtree.out","w",stdout);
            int i;
            n=gint();
            re(i,1,n-1){int x=gint(),y=gint();e[x].pb(y);e[y].pb(x);}
            bfs();
            int Q=gint();
            while(Q--)
              {
                  m=gint();
                    re(i,1,m)mark[h2[i]=h[i]=gint()]=i;
                    if(!mark[1])h[++m]=1;
                    build();
                    solve();
                    re(i,1,m)if(mark[h2[i]])PF("%d ",ans[h2[i]]),ans[h2[i]]=mark[h2[i]]=0;PF("
    ");
                }
            return 0;
      }
    View Code
  • 相关阅读:
    Node.js Path 模块
    Node.js OS 模块
    Node.js 工具模块
    【翻译】热门支持小提示:2013年12月
    【翻译】Sencha Touch 2入门:创建一个实用的天气应用程序之二
    俺的新书《Sencha Touch实战》终于出版了
    【翻译】热门支持技巧
    【翻译】Sencha Touch 2入门:创建一个实用的天气应用程序之一
    不错的东西: AutoMapper
    一个很不错的支持Ext JS 4的上传按钮
  • 原文地址:https://www.cnblogs.com/maijing/p/5218609.html
Copyright © 2011-2022 走看看