今天唯一的成果就是把上次几个人一起开房打的那场cf补一下。

A. Combination Lock

此等水题看一眼样例加上那个配图我就明白题意了,可是手抽没有注释掉freopen,WA了一发。

CodeForces Round #301 Div.2_i++CodeForces Round #301 Div.2_i++_02
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 1000 + 10;
 5 
 6 char s1[maxn], s2[maxn];
 7 
 8 int main()
 9 {
10     int n; cin >> n;
11     scanf("%s", s1);
12     scanf("%s", s2);
13     int ans = 0;
14     for(int i = 0; i < n; i++)
15     {
16         int a = s1[i] - '0';
17         int b = s2[i] - '0';
18         if(a < b) swap(a, b);
19         ans += min(a - b, 10 - a + b);
20     }
21     cout << ans << "\n";
22 
23     return 0;
24 }
代码君

 

B. School Marks

这道题本身不难,因为所给的n是奇数。但有可能会想错细节或漏掉情况。

n个数排好序,中间那个数一定是中位数,而且左右两边各n / 2个数。

所以我们看已知的k个数中比y小的数有多少个,如果大于n/2个,那么中位数一定小于y,无解。

如果k个数中不小于y的大于n / 2个,那么根据贪心,中位数已经在这些数里面了,所以剩下的n-k个数补成1就好了。

其次可以把中位数y插到这里面去,而且能算出中位数左边要补多少个1,右边要补多少个y。

注意在上面所有的情况中还要判断总数是否不超过x。

CodeForces Round #301 Div.2_i++CodeForces Round #301 Div.2_i++_02
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 1000 + 10;
 5 int a[maxn];
 6 
 7 int main()
 8 {
 9     //freopen("in.txt", "r", stdin);
10 
11     int n, k, p, x, y;
12     cin >> n >> k >> p >> x >> y;
13     for(int i = 0; i < k; i++) scanf("%d", &a[i]);
14     sort(a, a + k);
15     int t = lower_bound(a, a + k, y) - a;
16     if(t > n / 2) { puts("-1"); return 0; }
17 
18     int s = 0;
19     for(int i = 0; i < k; i++) s += a[i];
20     if(k - t > n / 2)
21     {
22         int p = n - k;
23         if(s + p > x) { puts("-1"); return 0; }
24         printf("1");
25         for(int i = 1; i < p; i++) printf(" 1");
26         puts(""); return 0;
27     }
28 
29     int l = n / 2 - t;
30     int r = n / 2 - k + t;
31     if(s + l + (r + 1) * y > x) { puts("-1"); return 0; }
32     bool print = false;
33     for(int i = 0; i < l; i++) { if(print) printf(" "); print = true; printf("1"); }
34     for(int i = 0; i <= r; i++) { if(print) printf(" "); print = true; printf("%d", y); }
35 
36     return 0;
37 }
代码君

 

C. Ice Cave (BFS)

总体来说这场CF难度偏易,虽然比赛的时候逗比地爆一了。但是下来的时候,手写一遍,没有编译错误交上去还过了,比赛要是这状态,啧啧

这道题一开始没有理解题意,其实就是地图上的'.'走过一遍就变成'X',而且'X'就不能再走了,终点除外。

问从能否起点走到终点,而且把终点变成'X'

把题意理解了,直接BFS就好啦,而且vis标记都不用,直接修改地图就好了。

CodeForces Round #301 Div.2_i++CodeForces Round #301 Div.2_i++_02
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 500 + 10;
 5 
 6 char s[maxn][maxn];
 7 int n, m;
 8 
 9 struct Node
10 {
11     int x, y;
12     Node(int x = 0, int y = 0):x(x), y(y) {}
13 }st, ed;
14 
15 int dx[] = { 1, 0, -1, 0 };
16 int dy[] = { 0, 1, 0, -1 };
17 
18 inline bool in(int x, int y) { return x > 0 && x <= n && y > 0 && y <= m; }
19 
20 bool BFS()
21 {
22     queue<Node> Q;
23     Q.push(st);
24     while(!Q.empty())
25     {
26         Node now = Q.front(); Q.pop();
27         for(int i = 0; i < 4; i++)
28         {
29             int x = now.x + dx[i];
30             int y = now.y + dy[i];
31             if(!in(x, y)) continue;
32             if(s[x][y] == 'X') { if(x == ed.x && y == ed.y) return true; continue; }
33             s[x][y] = 'X';
34             Q.push(Node(x, y));
35         }
36     }
37     return false;
38 }
39 
40 int main()
41 {
42     //freopen("in.txt", "r", stdin);
43 
44     cin >> n >> m;
45     for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
46     scanf("%d%d%d%d", &st.x, &st.y, &ed.x, &ed.y);
47     printf("%s\n", BFS() ? "YES" : "NO");
48 
49     return 0;
50 }
代码君

 

D. Bad Luck Island (概率 DP)

题解写得很清楚,递推或者DFS都行。

CodeForces Round #301 Div.2_i++CodeForces Round #301 Div.2_i++_02
 1 #include <cstdio>
 2 #include <iostream>
 3 using namespace std;
 4 
 5 const int maxn = 100 + 5;
 6 double d[maxn][maxn][maxn];
 7 
 8 int main()
 9 {
10     int a, b, c;
11     cin >> a >> b >> c;
12     d[a][b][c] = 1.0;
13     for(int i = a; i >= 0; i--)
14         for(int j = b; j >= 0; j--)
15             for(int k = c; k >= 0; k--)
16             {
17                 if(!i && !j) continue;
18                 if(!i && !k) continue;
19                 if(!j && !k) continue;
20                 double cur = d[i][j][k];
21                 double tot = i*j + i*k + j*k;
22                 if(i) d[i-1][j][k] += cur * (double)(i*k) / tot;
23                 if(j) d[i][j-1][k] += cur * (double)(i*j) / tot;
24                 if(k) d[i][j][k-1] += cur * (double)(j*k) / tot;
25             }
26 
27     double aa = 0, bb = 0, cc = 0;
28     for(int i = 1; i <= a; i++) aa += d[i][0][0];
29     for(int i = 1; i <= b; i++) bb += d[0][i][0];
30     for(int i = 1; i <= c; i++) cc += d[0][0][i];
31 
32     printf("%.12f %.12f %.12f\n", aa, bb, cc);
33 
34     return 0;
35 }
代码君

 

E. Infinite Inversions (树状数组 离散化)

可以把所求分成两个部分来计:

把这2n个数进行一次离散化,比如排序去重以后变成m个数。

那么经过m次操作,这m个数相较于初始状态是一个这m个数的排列。所以可以用树状数组计算一个这m个数之间的逆序数,注意这里不涉及位置没有变化的那些数。

这样我们便完成了第一部分的计数。

剩下的一部分是这m个数与其他位置未发生变化的逆序数。

预处理一下m个数中第i个数与第1个数之间有多少个数未发生位置改动sum[i]。

比如这m个数经过n次两两交换以后,第i个数的大小为rank[i],那么未发生位置改动的数与第i个数构成的逆序对有abs(sum[i] - sum[rank[i]])

举个栗子

比如2 7互换,序列由

1 2 3 4 5 6 7 8 变成 1 7 3 4 5 6 2 8

2和7之间有4个数没有变(即3 4 5 6),对于2 7而言,7到2前面去了这是一个逆序对,也就是我们计数的第一部分。

对于2来说,2在7的位置,而且3 4 5 6都与2构成一个逆序对,因此贡献了4个逆序对;

对于7同样,7在2的位置,3 4 5 6在7的后面也贡献了4个逆序对。

所以最终答案为9

CodeForces Round #301 Div.2_i++CodeForces Round #301 Div.2_i++_02
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 typedef long long LL;
 8 const int maxn = 200000 + 10;
 9 
10 int a[maxn], b[maxn], x[maxn], r[maxn];
11 LL sum[maxn], s[maxn];
12 int n, m;
13 
14 inline int lowbit(int x) { return x&(-x); }
15 
16 void add(int x, LL d)
17 { while(x <= m) { s[x] += d; x += lowbit(x); } }
18 
19 LL query(int x)
20 {
21     LL ans = 0;
22     while(x) { ans += s[x]; x -= lowbit(x); }
23     return ans;
24 }
25 
26 int main()
27 {
28     //freopen("in.txt", "r", stdin);
29 
30     cin >> n;
31     for(int i = 1; i <= n; i++)
32     {
33         scanf("%d%d", &a[i], &b[i]);
34         x[i*2-1] = a[i]; x[i*2] = b[i];
35     }
36     sort(x + 1, x + 1 + n*2);
37     m = unique(x + 1, x + 1 + n*2) - x - 1;
38     for(int i = 1; i <= m; i++)
39     {
40         sum[i] = sum[i - 1] + x[i] - x[i - 1] - 1;
41         r[i] = i;
42     }
43     for(int i = 1; i <= n; i++)
44     {
45         int ta = lower_bound(x + 1, x + 1 + m, a[i]) - x;
46         int tb = lower_bound(x + 1, x + 1 + m, b[i]) - x;
47         swap(r[ta], r[tb]);
48     }
49 
50     LL inv = 0;
51     for(int i = m; i > 0; i--)
52     {
53         inv += query(r[i]);
54         add(r[i], 1);
55         inv += abs(sum[i] - sum[r[i]]);
56     }
57 
58     cout << inv << endl;
59 
60     return 0;
61 }
代码君