zoukankan      html  css  js  c++  java
  • Kattis:Boxes

    Kattis:Boxes

    题目链接:https://open.kattis.com/problems/boxes

    题目大意:给出$N$个盒子,第$i$个盒子在第$a_i$个盒子内.现在有$Q$个询问,每个询问以$M$开始,问$M$个盒子中共有几个不同的盒子(包含自身).

    LCA

    在线LCA算法:

    树上两点$u$,$v$的最近公共祖先$A$的深度一定为$u$与$v$的简单路径中各点深度的最小值.

    我们可以用$ver[2 imes N]$数组按顺序记录dfs先后进出的结点编号(因为记录进出的结点,故有$2 imes N - 1$个元素),以将树形结构拆分为线性结构;用$dep[2 imes N]$数组记录对应结点的深度;用$f[i]$记录第一次进入第$i$个结点时在$ver[2 imes N]$中的下标.

    例如下图中,$ver[\,]={1,2,4,2,1,3,1}$,$dep[\,]={0,1,2,1,0,1,0}$,$f[\,]={-1,0,1,5,2}$(用$-1$表示结点$0$不存在)

    于是,求$u$与$v$的简单路径中各点深度的最小值,即求$ver[\,f[u]\,]$到$ver[\,f[u]\,]$中各结点深度的最小值(这其中可能会包含$u$的子结点,但其深度必然大于$u$的深度).

    而维护$ver[\,f[u]\,]$到$ver[\,f[u]\,]$中各结点深度的最小值,即维护一个线性区间的最小值,采用rmq算法,预处理复杂度为$O(nlgn)$,查询复杂度为$O(1)$.


    设$A$为$x$与$y$的最近公共祖先,即$A=LCA(x,y)$.

    若$A=x$,则$y$在$x$内;

    若$A=y$,则$x$在$y$内;

    若$A eq x$且$A eq y$,则$x$和$y$互不包含.

    两两枚举最近公共祖先,舍去被包含的结点并用set去重,就可以解决这道题了.

    //注意:

    //可能不止有一个盒子不被其他盒子包含(因为这个问题卡了三天QAQ)

    //可以添加一个虚结点下标为$0$,从而构成一颗树.

    整道题的时间复杂度为$O(nlgn+q imes m^2)$

    代码如下:

     1 #include <iostream>
     2 #include <vector>
     3 #include <cmath>
     4 #include <set>
     5 #define pb(x) push_back(x)
     6 #define N 200005
     7 #define M 25
     8 #define P 20
     9 using namespace std;
    10 vector<int>a[N];
    11 set<int>s;
    12 int n,q,m,tmp,ans,qm[M];
    13 int k,ver[2*N],dep[2*N],f[N],num[N],dp[2*N][P];
    14 int dfs(int x,int d){
    15     num[x]=1;
    16     f[x]=k;
    17     dep[k]=d;
    18     ver[k++]=x;
    19     for(int i=0;i<(int)a[x].size();++i){
    20         num[x]+=dfs(a[x][i],d+1);
    21         dep[k]=d;
    22         ver[k++]=x;
    23     }
    24     return num[x];
    25 }
    26 void rmq(int k){
    27     for(int i=0;i<k;++i)
    28         dp[i][0]=i;
    29     for(int j=1;(1<<j)<=k;++j)
    30     for(int i=0;i+(1<<j)<=k;++i){
    31         int x=dp[i][j-1],y=dp[i+(1<<(j-1))][j-1];
    32         dp[i][j]=dep[x]<dep[y]?x:y;
    33     }
    34 }
    35 int LCA(int u,int v){
    36     if(u>v)swap(u,v);
    37     int len=log(v-u+1.0)/log(2.0);
    38     int x=dp[u][len],y=dp[v+1-(1<<len)][len];
    39     return ver[dep[x]<dep[y]?x:y];
    40 }
    41 int main(void){
    42     std::ios::sync_with_stdio(false);
    43     cin>>n;
    44     for(int i=1;i<=n;++i){
    45         cin>>tmp;
    46         a[tmp].pb(i);
    47     }
    48     dfs(0,0);
    49     rmq(k);
    50     cin>>q;
    51     while(q--){
    52         s.clear();
    53         cin>>m;
    54         for(int i=0;i<m;++i)
    55             cin>>qm[i];
    56         for(int i=0;i<m;++i){
    57             int tot=qm[i];
    58             for(int j=0;j<m;++j){
    59                 tmp=LCA(f[tot],f[qm[j]]);
    60                 if(tmp==qm[j])tot=tmp;
    61             }
    62             s.insert(tot);
    63         }
    64         ans=0;
    65         for(set<int>::iterator it=s.begin();it!=s.end();++it)
    66             ans+=num[*it];
    67         cout<<ans<<"
    ";
    68     }
    69 }
  • 相关阅读:
    关键词user附近有语法错误
    Java期末考试冲刺总结
    getElementsByName&getElementById
    window.location.herf传值问题
    三种提示框
    statement没有返回结果集问题
    ajax从jsp向servlet传值
    java.sql.SQLException: Access denied for user ''@'localhost' (using password: NO)报错问题解决
    Unregistering application product with eureka with status DOWN
    输出废弃
  • 原文地址:https://www.cnblogs.com/barrier/p/6476275.html
Copyright © 2011-2022 走看看