Codeforces Round #199 (Div. 2)
A. Xenia and Divisors 水题
B. Xenia and Spies 水题
C. Cupboard and Balloons 水题
D. Xenia and Dominoes
DP:保存每一列的状态,一列一列的向后递推
1 #include <cstdio>
2 #include <cstring>
3 #include <algorithm>
4 #include <cmath>
5 #include <queue>
6 #include <string>
7 #include <map>
8 #include <set>
9 #include <iostream>
10 #include <ctime>
11 using namespace std;
12 #define clr(a, b) memset(a, b, sizeof(a))
13 #define sqr(x) ((x) * (x))
14 #define ABS(x) max(x, -x)
15 #define SB puts("sb");
16 #define L(i) (i << 1)
17 #define R(i) ((i << 1) | 1)
18 typedef long long ll;
19 const int INF = 0x3f3f3f3f;
20 const int MOD = 1000000007;
21 const int N = 10010;
22 const int M = 1;
23
24 char s[4][N];
25 int n, dp[N][8];
26 int sx, sy;
27
28 void find() {
29 for (int i = 1; i <= 3; ++i)
30 for (int j = 1; j <= n; ++j) if (s[i][j] == 'O') {
31 sx = i, sy = j;
32 return;
33 }
34 }
35
36 int num(int j) {
37 int ret = 0;
38 for (int i = 1; i <= 3; ++i) if (s[i][j] != '.') {
39 ret += (1 << (3 - i));
40 }
41 return ret;
42 }
43
44 int cal_mode(int i, int k) {
45 if (k == 0) return dp[i - 1][7];
46 if (k == 1) return dp[i - 1][6];
47 if (k == 2) return dp[i - 1][5];
48 if (k == 3) return (dp[i - 1][7] + dp[i - 1][4]) % MOD;
49 if (k == 4) return dp[i - 1][3];
50 if (k == 5) return dp[i - 1][2];
51 if (k == 6) return (dp[i - 1][7] + dp[i - 1][1]) % MOD;
52 if (k == 7) return ((dp[i - 1][0] + dp[i - 1][3]) % MOD + dp[i - 1][6]) % MOD;
53 return 0;
54 }
55
56 int cal() {
57 clr(dp, 0);
58 dp[0][7] = 1;
59
60 for(int i = 1; i <= n; ++i)
61 {
62 int k = num(i);
63 for (int j = k; j <= 7; ++j) if((j & k) == k)
64 dp[i][j] = cal_mode(i, j - k);
65 }
66 return dp[n][7];
67 }
68
69
70 int main()
71 {
72 freopen("in", "r", stdin);
73 freopen("out", "w", stdout);
74 scanf("%d", &n);
75 for (int i = 1; i <= 3; ++i) scanf("%s", s[i] + 1);
76
77 find();
78
79 if (sx == 2) {
80 int ans = 0;
81 bool f1 = 0, f2 = 0;
82 if (sy >= 3) {
83 if (s[2][sy - 2] == '.' && s[2][sy - 1] == '.') {
84 f1 = 1;
85 s[2][sy - 2] = s[2][sy - 1] = 'X';
86 ans += cal();
87 s[2][sy - 2] = s[2][sy - 1] = '.';
88 }
89 }
90 if (sy + 2 <= n) {
91 if (s[2][sy + 2] == '.' && s[2][sy + 1] == '.') {
92 f2 = 1;
93 s[2][sy + 2] = s[2][sy + 1] = 'X';
94 ans += cal();
95 s[2][sy + 2] = s[2][sy + 1] = '.';
96 }
97 }
98 if (f1 && f2) {
99 s[2][sy - 2] = s[2][sy - 1] = 'X';
100 s[2][sy + 2] = s[2][sy + 1] = 'X';
101 ans -= cal();
102 }
103 if (ans < 0) ans += MOD;
104 printf("%d\n", ans % MOD);
105 }
106 else
107 printf("%d\n", cal());
108 return 0;
109 }
E. Xenia and Tree
此题的数据不给力啊,直接暴力的程序都过了。。。
当要修改的节点数大于一定范围lim时,bfs一遍,修改所有节点的答案;否则先放到队列里,遇到查询直接用在线LCA求一下答案,至于范围lim,我觉得sqrt(n)比较合适,虽然没有直接暴力的程序快。。。
code 1:
1 #include <cstdio>
2 #include <cstring>
3 #include <cmath>
4 #include <algorithm>
5 using namespace std;
6 const int N = 100010;
7 #define clr(a, b) memset(a, b, sizeof(a))
8
9 int n, m, p[N][18], dis[N], d[N];
10 int head[N], pre[N * 2], nxt[N * 2], e;
11 int q[N], st, ed;
12 bool inq[N];
13
14 void init() {
15 clr(head, -1);
16 clr(p, -1);
17 e = 0;
18 }
19
20 void addedge(int u, int v) {
21 pre[e] = v, nxt[e] = head[u], head[u] = e++;
22 pre[e] = u, nxt[e] = head[v], head[v] = e++;
23 }
24
25 void dfs(int u, int f) {
26 p[u][0] = f;
27 if (~f) d[u] = d[f] + 1;
28 for (int i = 0; ~p[u][i]; ++i)
29 p[u][i + 1] = p[ p[u][i] ][i];
30 for (int i = head[u]; ~i; i = nxt[i]) {
31 int v = pre[i];
32 if (v == f) continue;
33 dfs(v, u);
34 }
35 }
36
37 int OnlineLCA(int u, int v) {
38 if (d[u] < d[v]) swap(u, v);
39 int del = d[u] - d[v];
40 for (int i = 0; del; ++i) if (del & (1 << i)) {
41 del -= (1 << i);
42 u = p[u][i];
43 }
44 int lim = ceil(log(d[u]) / log(2));
45 if (u != v) {
46 for (int i = lim; i >= 0; --i) if(p[u][i] != p[v][i]) {
47 u = p[u][i];
48 v = p[v][i];
49 }
50 u = p[u][0];
51 }
52 return u;
53 }
54
55 void bfs() {
56 clr(inq, 0);
57 while (st <= ed) {
58 int u = q[st++];
59 for (int i = head[u]; ~i; i = nxt[i]) {
60 int v = pre[i];
61 if (dis[v] > dis[u] + 1) {
62 dis[v] = dis[u] + 1;
63 if (!inq[v]) {
64 q[++ed] = v;
65 inq[v] = 1;
66 }
67 }
68 }
69 }
70 }
71
72 int main() {
73 freopen("in", "r", stdin);
74 freopen("out", "w", stdout);
75 init();
76 scanf("%d%d", &n, &m);
77 int x, y;
78 for (int i = 1; i < n; ++i) {
79 scanf("%d%d", &x, &y);
80 addedge(x, y);
81 }
82 dfs(1, -1);
83
84 memcpy(dis, d, sizeof(d));
85 int block = (int)sqrt(n + 0.5);
86
87 st = 0, ed = -1;
88
89 while (m--) {
90 scanf("%d%d", &x, &y);
91 if (x == 1) {
92 q[++ed] = y;
93 dis[y] = 0;
94 }
95 else {
96 if (ed - st > block) {
97 bfs();
98 printf("%d\n", dis[y]);
99 st = 0, ed = -1;
100 }
101 else {
102 int ans = dis[y];
103 for (int i = st; i <= ed; ++i) {
104 int anc = OnlineLCA(y, q[i]);
105 ans = min(ans, d[y] + d[ q[i] ] - 2 * d[anc]);
106 }
107 printf("%d\n", ans);
108 }
109 }
110 }
111 return 0;
112 }
code 2:
1 #include <cstdio>
2 #include <cstring>
3 #include <cmath>
4 #include <algorithm>
5 using namespace std;
6 const int N = 200010;
7 #define clr(a, b) memset(a, b, sizeof(a))
8
9 int n, m, dis[N], d[N], dfn[N], cnt, euler[N];
10 int head[N], pre[N], nxt[N], e;
11 int q[N], st, ed;
12 bool inq[N];
13
14 void init() {
15 clr(head, -1);
16 e = 0;
17 cnt = 0;
18 }
19
20 void addedge(int u, int v) {
21 pre[e] = v, nxt[e] = head[u], head[u] = e++;
22 pre[e] = u, nxt[e] = head[v], head[v] = e++;
23 }
24
25 struct RMQ {
26 int LOG[N], d[N][20];
27 RMQ() {
28 LOG[0] = -1;
29 for (int i = 1; i < N; ++i) LOG[i] = LOG[i >> 1] + 1;
30 }
31 void init(int *a, int *b, int n) {
32 for (int i = 1; i <= n; ++i) d[i][0] = b[i];
33 for (int j = 1; j <= LOG[n]; ++j)
34 for (int i = 1; j <= LOG[n - i] + 1; ++i) {
35 if (a[d[i][j-1]] < a[d[i + (1 << (j-1))][j-1]])
36 d[i][j] = d[i][j-1];
37 else
38 d[i][j] = d[i+(1<<(j-1))][j-1];
39 }
40 }
41 int query(int *a, int l, int r) {
42 int k = LOG[r - l + 1];
43 if (a[d[l][k]] < a[d[r- (1 << k) + 1][k]])
44 return d[l][k];
45 else
46 return d[r- (1 << k) + 1][k];
47 }
48 };
49 RMQ rq;
50
51 void dfs(int u, int f) {
52 euler[++cnt] = u;
53 dfn[u] = cnt;
54 d[u] = d[f] + 1;
55 for (int i = head[u]; ~i; i = nxt[i]) {
56 int v = pre[i];
57 if (v == f) continue;
58 dfs(v, u);
59 euler[++cnt] = u;
60 }
61 }
62
63 void bfs() {
64 clr(inq, 0);
65 while (st <= ed) {
66 int u = q[st++];
67 for (int i = head[u]; ~i; i = nxt[i]) {
68 int v = pre[i];
69 if (dis[v] > dis[u] + 1) {
70 dis[v] = dis[u] + 1;
71 if (!inq[v]) {
72 q[++ed] = v;
73 inq[v] = 1;
74 }
75 }
76 }
77 }
78 }
79
80 int OnlineLCA(int u, int v) {
81 if (dfn[u] > dfn[v]) swap(u, v);
82 return rq.query(d, dfn[u], dfn[v]);
83 };
84
85 int main() {
86 freopen("in", "r", stdin);
87 freopen("out", "w", stdout);
88 init();
89 scanf("%d%d", &n, &m);
90 int x, y;
91 for (int i = 1; i < n; ++i) {
92 scanf("%d%d", &x, &y);
93 addedge(x, y);
94 }
95
96 d[0] = -1;
97 dfs(1, 0);
98
99 rq.init(d, euler, 2 * n - 1);
100
101 memcpy(dis, d, sizeof(d));
102 int block = (int)sqrt(n + 0.5);
103
104 st = 0, ed = -1;
105 while (m--) {
106 scanf("%d%d", &x, &y);
107 if (x == 1) {
108 q[++ed] = y;
109 dis[y] = 0;
110 }
111 else {
112 if (ed - st > block) {
113 bfs();
114 printf("%d\n", dis[y]);
115 st = 0, ed = -1;
116 }
117 else {
118 int ans = dis[y];
119 for (int i = st; i <= ed; ++i) {
120 int anc = OnlineLCA(y, q[i]);
121 ans = min(ans, d[y] + d[q[i]] - 2 * d[anc]);
122 }
123 printf("%d\n", ans);
124 }
125 }
126 }
127 return 0;
128 }