zoukankan      html  css  js  c++  java
  • BZOJ 2851——极限满月

    http://61.187.179.132/JudgeOnline/problem.php?id=2851

    Description

    Input

    第一行一个正整数。
    之后行描述集合。第一个数表示集合中元素的个数,之后给出集合中的元素。
    之后一行一个正整数。
    之后行每行描述一个询问。格式与之前相同。

    Output

    对于每个询问,在单独的一行内输出答案。

    Sample Input

    7
    0
    1 1
    1 1
    1 2
    2 2 3
    0
    2 2 6
    3
    2 2 3
    2 3 5
    2 4 5

    Sample Output

    3
    3
    4

    HINT

     



    对于100% 的数据,1 <= n, m <= 50000,1 <= 10^9,-10^9 <= a, b, x, y <= 10^9。

     

    Source

    Violet 0

    题解:

      Violet 0的题果然不水,好题啊。

      我们观察A集合,如果把Ai中的数考虑为i的父亲的话(后缀也可以,看个人喜好),那么我们可以发现这张图是一个DAG,且Bi这个集合里面的数都是i在图中的灾难点,也就是说Bi是i的灾难点的集合。于是我们可以把灾难树建出来,然后对于每个询问就变成了求一些点的灾难点的集合的并的大小。我们把询问离线之后可以利用dfs序的先后关系处理掉可能重复的情况。

    View Code
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<vector>
      5 #include<cctype>
      6 
      7 using namespace std;
      8 
      9 const int maxn=200010;
     10 
     11 int q,en,n,depth[maxn],f[maxn][25],last_q[maxn],ans[maxn];
     12 
     13 vector<int> query[maxn],ed[maxn],set_a[maxn];
     14 
     15 const int BUF_SIZE = 1000;
     16 char buf[BUF_SIZE], *buf_s = buf, *buf_t = buf + 1;
     17   
     18 #define PTR_NEXT() \
     19     { \
     20         buf_s ++; \
     21         if (buf_s == buf_t) \
     22         { \
     23             buf_s = buf; \
     24             buf_t = buf + fread(buf, 1, BUF_SIZE, stdin); \
     25         } \
     26     }
     27    
     28 #define readint(_n_) \
     29     { \
     30         while (*buf_s != '-' && !isdigit(*buf_s)) \
     31             PTR_NEXT(); \
     32         bool register _nega_ = false; \
     33         if (*buf_s == '-') \
     34         { \
     35             _nega_ = true; \
     36             PTR_NEXT(); \
     37         } \
     38         int register _x_ = 0; \
     39         while (isdigit(*buf_s)) \
     40         { \
     41             _x_ = _x_ * 10 + *buf_s - '0'; \
     42             PTR_NEXT(); \
     43         } \
     44         if (_nega_) \
     45             _x_ = -_x_; \
     46         (_n_) = (_x_); \
     47     }
     48 
     49 
     50 void add_edge(int s,int e)
     51 {
     52     ed[s].push_back(e);
     53 }
     54 
     55 inline int get_lca(int p1,int p2)
     56 {
     57     if (depth[p1]<depth[p2]) swap(p1,p2);
     58     int now=0;
     59     int delta=depth[p1]-depth[p2];
     60     while (delta)
     61     {
     62         if (delta & 1) p1=f[p1][now];
     63         delta>>=1;
     64         now++;
     65     }
     66     now=0;
     67     while (p1!=p2)
     68     {
     69         if (f[p1][now]!=f[p2][now] || (f[p1][now]==f[p2][now] && now==0))
     70         {
     71             p1=f[p1][now];
     72             p2=f[p2][now];
     73             now++;
     74         }
     75         else now--;
     76     }
     77     return p1;
     78 }
     79 
     80 void dfs(int now)
     81 {
     82     int sz=query[now].size();
     83     for (int a=0;a<sz;a++)
     84     {
     85         int p=query[now][a];
     86         if (last_q[p]==-1) ans[p]+=depth[now]-1;
     87         else ans[p]+=depth[now]-depth[get_lca(now,last_q[p])];
     88         last_q[p]=now;
     89     }
     90     sz=ed[now].size();
     91     for (int a=0;a<sz;a++)
     92         dfs(ed[now][a]);
     93 }
     94 
     95 int main()
     96 {
     97     readint(n);
     98     memset(f[0],-1,sizeof(f[0]));
     99     depth[0]=1;
    100     for (int a=1;a<=n;a++)
    101     {
    102         int sz;
    103         readint(sz);
    104         for (int b=1;b<=sz;b++)
    105         {
    106             int v;
    107             readint(v);
    108             set_a[a].push_back(v);
    109         }
    110     }
    111     for (int a=1;a<=n;a++)
    112         if (!set_a[a].size()) 
    113         {
    114             add_edge(0,a);
    115             depth[a]=2;
    116             f[a][0]=0;
    117         }
    118         else
    119         {
    120             int lca=set_a[a][0];
    121             int sz=set_a[a].size();
    122             for (int b=1;b<sz;b++)
    123                 lca=get_lca(lca,set_a[a][b]);
    124             add_edge(lca,a);
    125             depth[a]=depth[lca]+1;
    126             int now=0;
    127             f[a][0]=lca;
    128             while (f[lca][now]!=-1)
    129             {
    130                 f[a][now+1]=f[lca][now];
    131                 lca=f[lca][now];
    132                 now++;
    133             }
    134         }
    135     readint(q);
    136     for (int a=1;a<=q;a++)
    137     {
    138         int sz;
    139         readint(sz);
    140         for (int b=1;b<=sz;b++)
    141         {
    142             int v;
    143             readint(v);
    144             query[v].push_back(a);
    145         }
    146     }
    147     memset(last_q,-1,sizeof(last_q));
    148     dfs(0);
    149     for (int a=1;a<=q;a++)
    150         printf("%d\n",ans[a]);
    151 
    152     return 0;
    153 }
  • 相关阅读:
    [转]flash builder 4 编译器参数
    三种简洁的经典高效的DIV+CSS制作的Tab导航简析
    《api解读》第三期
    AS3中的条件编译
    比较少见的绘制虚线的方法
    一个关于SharedObject存储位置的讨论
    《api解读》写在前面的话
    wampserver配置本地测试环境_虚拟主机实现多站点
    AS3中的正则表达式 Flex正则表达式
    Flixel引擎学习笔记
  • 原文地址:https://www.cnblogs.com/zhonghaoxi/p/2674301.html
Copyright © 2011-2022 走看看