CodeForces Round #301 Div.2

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

A. Combination Lock

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

 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。

 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标记都不用,直接修改地图就好了。

 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都行。

 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

 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 }
代码君

 

你可能感兴趣的:(codeforces)