CF 1033 C. Permutation Game

C. Permutation Game

http://codeforces.com/contest/1033/problem/C

题意:

  一个排列,每个位置i走到的位置j满足:a[j]>a[i],(j-i)是a[i]的倍数。问从每个位置开始,是否有必胜策略。

分析:

  博弈论+拓扑。

  由于是一个排列,那么可以枚举每个数,判断这个位置的a是否大于它,如果可以连边。这样的复杂度是$nlogn$的。

  然后对于一些无路可走的点,这是必败态,根据必胜和必败的定义:必胜态的后继状态中存在至少一个必败态,必败态的后继状态全是必胜态。

  然后建反图,在DAG上拓扑。

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 #include<set>
 8 #include<vector>
 9 #include<queue>
10 #include<map>
11 #define fi(s) freopen(s,"r",stdin);
12 #define fo(s) freopen(s,"w",stdout);
13 using namespace std;
14 typedef long long LL;
15 
16 inline int read() {
17     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
18     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
19 }
20 
21 
22 const int N = 1000005;
23 int a[N], deg[N], q[N], f[N];
24 vector<int>T[N];
25 
26 int main() {
27     int n = read();
28     for (int i=1; i<=n; ++i) a[i] = read();
29     
30     for (int i=1; i<=n; ++i) {
31         for (int j=i+a[i]; j<=n; j+=a[i]) 
32             if (a[j] > a[i]) T[j].push_back(i), deg[i] ++;
33         for (int j=i-a[i]; j>=1; j-=a[i]) 
34             if (a[j] > a[i]) T[j].push_back(i), deg[i] ++;
35     }
36 
37     int L = 1, R = 0;
38     memset(f, -1, sizeof(f));
39     for (int i=1; i<=n; ++i) 
40         if (!deg[i]) q[++R] = i, f[i] = 0;
41     
42     while (L <= R) {
43         int u = q[L ++];
44         for (int sz=T[u].size(),i=0; i<sz; ++i) {
45             int v = T[u][i];
46             if (f[v] == -1) {
47                 if (f[u] == 0) f[v] = 1;
48                 else f[v] = 0;
49             }
50             else {
51                 if (f[u] == 0) f[v] = 1;
52             }
53             deg[v] --;
54             if (!deg[v]) q[++R] = v;
55         }
56     }
57     for (int i=1; i<=n; ++i) { 
58         if (f[i]) putchar('A');
59         else putchar('B');
60     }
61     return 0;
62 }

猜你喜欢

转载自www.cnblogs.com/mjtcn/p/9754605.html