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
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
3
4
HINT
对于100% 的数据,1 <= n, m <= 50000,1 <= 10^9,-10^9 <= a, b, x, y <= 10^9。
Source
题解:
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 }