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
", ans % MOD);
105     }
106     else
107         printf("%d
", cal());
108     return 0;
109 }
View Code

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
", 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
", ans);
108             }
109         }
110     }
111     return 0;
112 }
View Code

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
", 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
", ans);
124             }
125         }
126     }
127     return 0;
128 }
View Code
原文地址:https://www.cnblogs.com/NEIL74/p/3307725.html