BYRBT

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 }

 

posted @ 2012-09-06 22:40  zhonghaoxi  阅读(349)  评论(0编辑  收藏  举报
BYRBT