zoukankan      html  css  js  c++  java
  • Codeforces Round #326 Div.1 C.Duff in the Army 树上倍增

    题意概述:

    给出一棵N个结点的树,然后有M个居民分散在这棵树的结点上(允许某个结点没有居民)。现在给出一些询问形如u,v,a,定义k=min(x,a),其中x表示的是u->v路径上的居民数量。将所有路径上的居民编号升序排列之后得到序列p1,p2,...,px,要求对于每一组询问,输出k,p1,p2,...,pk。

    N,M,Q<=10^5,1<=a<=10.

    分析:

    实际上这个题是被丢在数据结构作业里面的只是。。。。好像没有这个必要?

    分析一波可以发现每个点可能在答案中出现的居民最多只有10个,所以说按照出现的顺序依次把每个点的至多10个居民储存起来,然后倍增的时候用归并排序的思想合并就可以了。时间复杂度O(10nlogn)。

    实现过程中注意到一些问题,今后用倍增统计点的信息的时候都用半开半闭就好了,加上对链顶端(x=y时对x,否则x,y一起爬之后对x,y,fa[x][0])的特判就可以做到不重不漏统计(之前都是用来求最值之类的所以没有注意到这个问题)。

    所以。。。数据结构是树的意思吗。。。。(感觉听了小火车讲课之后写代码的时候都在各种压长度?)

    所以这个时限的4s是输入输出的锅?(实测手写0.5s的事情)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<queue>
     8 #include<set>
     9 #include<map>
    10 #include<vector>
    11 #include<cctype>
    12 using namespace std;
    13 const int maxn=100005;
    14 
    15 int N,M,Q;
    16 struct edge{ int to,next; }E[maxn<<1];
    17 int first[maxn],np,dep[maxn],fa[maxn][17],info[maxn][17][10],sz[maxn][17];
    18 int ans[25],tmp[25];
    19 
    20 void add_edge(int u,int v)
    21 {
    22     E[++np]=(edge){v,first[u]};
    23     first[u]=np;
    24 }
    25 void data_in()
    26 {
    27     scanf("%d%d%d",&N,&M,&Q);
    28     int x,y;
    29     for(int i=1;i<N;i++){
    30         scanf("%d%d",&x,&y);
    31         add_edge(x,y);
    32         add_edge(y,x);
    33     }
    34     for(int i=1;i<=M;i++){
    35         scanf("%d",&x);
    36         if(sz[x][0]<10) info[x][0][sz[x][0]++]=i;
    37     }
    38 }
    39 int merge(int *a,int *b,int l1,int l2,int *c)
    40 {
    41     int l=0,i=0,j=0;
    42     while(i<l1&&j<l2&&l<10) c[l++]=a[i]<b[j]?a[i++]:b[j++];
    43     while(i<l1&&l<10) c[l++]=a[i++];
    44     while(j<l2&&l<10) c[l++]=b[j++];
    45     return l;
    46 }
    47 void DFS(int i,int f,int d)
    48 {
    49     fa[i][0]=f,dep[i]=d;
    50     for(int j=1;(1<<j)<d;j++){
    51         fa[i][j]=fa[fa[i][j-1]][j-1];
    52         sz[i][j]=merge(info[i][j-1],info[fa[i][j-1]][j-1],sz[i][j-1],sz[fa[i][j-1]][j-1],info[i][j]);
    53     }
    54     for(int p=first[i];p;p=E[p].next){
    55         int j=E[p].to;
    56         if(j==f) continue;
    57         DFS(j,i,d+1);
    58     }
    59 }
    60 void cc(int *n,int &l,int x,int i)
    61 {
    62     l=merge(n,info[x][i],l,sz[x][i],tmp);
    63     for(int k=0;k<l;k++) n[k]=tmp[k];
    64 }
    65 void LCA(int x,int y,int *n,int &l)
    66 {
    67     if(dep[x]<dep[y]) swap(x,y);
    68     int len=dep[x]-dep[y]; l=0;
    69     for(int i=0;(1<<i)<=len;i++)
    70         if((1<<i)&len){ cc(n,l,x,i); x=fa[x][i]; }
    71     if(x==y){ cc(n,l,x,0); return; }
    72     for(int i=16;i>=0;i--) if(fa[x][i]!=fa[y][i]){
    73         cc(n,l,x,i); cc(n,l,y,i);
    74         x=fa[x][i],y=fa[y][i];
    75     }
    76     cc(n,l,x,0); cc(n,l,y,0);
    77     cc(n,l,fa[x][0],0);
    78 }
    79 void work()
    80 {
    81     DFS(1,0,1);
    82     int x,y,a,l;
    83     for(int i=1;i<=Q;i++){
    84         scanf("%d%d%d",&x,&y,&a);
    85         LCA(x,y,ans,l);
    86         printf("%d ",min(a,l));
    87         for(int j=0;j<min(a,l);j++) printf("%d ",ans[j]);
    88         printf("
    ");
    89     }
    90 }
    91 int main()
    92 {
    93 data_in(); 94 work(); 95 return 0; 96 }
  • 相关阅读:
    hdu6007 Mr. Panda and Crystal 最短路+完全背包
    ID生成器的一种可扩展实现方案
    使用PUT方法上传文件无法工作原因分析
    负载均衡算法
    父类和子类属性覆盖的各种情况分析
    java functional syntax overview
    Starter Set of Functional Interfaces
    application/xml和text/xml的区别
    mime type 概要介绍
    spring mvc 详细执行流程
  • 原文地址:https://www.cnblogs.com/KKKorange/p/8459945.html
Copyright © 2011-2022 走看看