Codeforces Round #622 (Div. 2)

比较难的一场,幸好过A之后看了一眼dashboard,不然没了

题目链接:https://codeforces.com/contest/1313


A:

sort一下直接7个if贪心。

 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define pb emplace_back
 6 #define mp make_pair
 7 #define eps 1e-8
 8 #define lson (curpos<<1)
 9 #define rson (curpos<<1|1)
10 /* namespace */
11 using namespace std;
12 /* header end */
13 
14 int t;
15 
16 int main() {
17     scanf("%d", &t);
18     while (t--) {
19         int a, b, c, ans = 0, flag[10];
20         memset(flag, 0, sizeof(flag));
21         scanf("%d%d%d", &a, &b, &c);
22         int tmp[3] = {a, b, c};
23         sort(tmp, tmp + 3);
24         a = tmp[2], b = tmp[1], c = tmp[0];
25         while (1) {
26             if (a >= 1 && !flag[1]) {
27                 a -= 1; flag[1] = 1; ans++; continue;
28             }
29             if (b >= 1 && !flag[2]) {
30                 b -= 1; flag[2] = 1; ans++; continue;
31             }
32             if (c >= 1 && !flag[3]) {
33                 c -= 1; flag[3] = 1; ans++; continue;
34             }
35             if (a >= 1 && b >= 1 && !flag[4]) {
36                 a -= 1, b -= 1; flag[4] = 1; ans++; continue;
37             }
38             if (a >= 1 && c >= 1 && !flag[5]) {
39                 a -= 1, c -= 1; flag[5] = 1; ans++; continue;
40             }
41             if (b >= 1 && c >= 1 && !flag[6]) {
42                 b -= 1, c -= 1; flag[6] = 1; ans++; continue;
43             }
44             if (a >= 1 && b >= 1 && c >= 1 && !flag[7]) {
45                 a -= 1, b -= 1, c -= 1; flag[7] = 1; ans++; continue;
46             }
47             break;
48         }
49         printf("%d
", ans);
50     }
51     return 0;
52 }
View Code

B:

出得挺好的题。题意如下:

有n个人参加比赛,比赛分为两轮,每一轮均不会出现并列名次的情况,每个人最后得分为两轮排名之和,分数越小排名越高(会出现并列的情况)。现已知某人第一、二轮排名,问此人(以下称为A)排名最高最低分别为多少。

最坏情况非常简单,显然为min(n, x+y-1),难点在于最好情况的推导。如果我们希望某人排名比A低,那么最优做法就是让某人分数为x+y+1,此时我们需要分类讨论:

如果x+y<=n,那么对于其他人,若第一场排名为p,必然能让其在第二场排名为x+y+1-p甚至更高,从而使得其最终排名变低,此时A的排名为第一名。

如果x+y>n,那么对于其他人,若第一场排名为p,则让其第二场排名也为p,这样就能使得本身排名靠前的人继续靠前,这样我们就能忽略掉这个人,剩下的人就变成了一个规模小一点的子问题,而且剩下的人相对排名也会变小。重复这个过程直到x+y<=n,就变成了刚刚熟悉的场景,可以轻松解决。假设我们让t个人两轮排名相同,那么显然有x-t+y-t=n-t, t=x+y-n,此时A的排名一定为x+y-n+1。

注意最小值要与1取max,最大值要与n取min。

 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define pb emplace_back
 6 #define mp make_pair
 7 #define eps 1e-8
 8 #define lson (curpos<<1)
 9 #define rson (curpos<<1|1)
10 /* namespace */
11 using namespace std;
12 /* header end */
13 
14 int t;
15 
16 int main() {
17     scanf("%d", &t);
18     while (t--) {
19         int n, x, y;
20         scanf("%d%d%d", &n, &x, &y);
21         printf("%d %d
", max(1, min(n, x + y + 1 - n)), min(x + y - 1, n));
22     }
23     return 0;
24 }
View Code

C1:

n==1000,直接O(n^2)暴力更新答案。

 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define pb emplace_back
 6 #define mp make_pair
 7 #define eps 1e-8
 8 #define lson (curpos<<1)
 9 #define rson (curpos<<1|1)
10 /* namespace */
11 using namespace std;
12 /* header end */
13 
14 const int maxn = 1010;
15 int n, a[maxn], m[maxn], ansList[maxn];
16 ll ans = 0;
17 
18 int main() {
19     scanf("%d", &n);
20     for (int i = 1; i <= n; i++) scanf("%d", &m[i]);
21     for (int i = 1; i <= n; i++) {
22         ll total = 0;
23         for (int j = 1; j < i; j++) a[j] = 0;
24         for (int j = i + 1; j <= n; j++) a[j] = 0;
25         a[i] = m[i]; total += a[i];
26         for (int j = i - 1; j >= 1; j--) {
27             a[j] = min(m[j], a[j + 1]);
28             total += a[j];
29         }
30         for (int j = i + 1; j <= n; j++) {
31             a[j] = min(m[j], a[j - 1]);
32             total += a[j];
33         }
34         if (total > ans) {
35             ans = total;
36             for (int i = 1; i <= n; i++) ansList[i] = a[i];
37         }
38     }
39     for (int i = 1; i <= n; i++) printf("%d ", ansList[i]);
40     return 0;
41 }
View Code

C2:

与上一题的区别是n==5e5。

考虑分治,solve(l,r)代表当前处理到[l,r]这个区间。假设区间最小值为a[mid],那么必然要把区间[l,mid-1]或[mid+1,r]里的元素都变为a[mid],否则不符合题意。

倘若我们令区间[l,mid-1]里的元素都变为a[mid],此时总和为(mid-l+1)*a[mid]+solve(mid+1,r);若令区间[mid+1,r]里的元素都变为a[mid],此时总和为(r-mid+1)*a[mid]+solve(l,mid-1)。

只要比较一下这两个和的大小,并维护方案即可。

 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define pb emplace_back
 6 #define mp make_pair
 7 #define eps 1e-8
 8 #define lson (curpos<<1)
 9 #define rson (curpos<<1|1)
10 /* namespace */
11 using namespace std;
12 /* header end */
13 
14 const int maxn = 5e5 + 10;
15 int n;
16 ll a[maxn], ans[maxn];
17 
18 struct Node {
19     ll val;
20     int pos;
21     Node() {}
22     Node(ll x, int y): val(x), pos(y) {}
23     bool operator<(const Node &rhs)const {
24         if (val != rhs.val) return val < rhs.val;
25         else return pos < rhs.pos;
26     }
27 } segt[maxn << 2];
28 
29 void maintain(int curpos) {
30     if (segt[lson].val > segt[rson].val) {
31         segt[curpos].val = segt[rson].val;
32         segt[curpos].pos = segt[rson].pos;
33     } else {
34         segt[curpos].val = segt[lson].val;
35         segt[curpos].pos = segt[lson].pos;
36     }
37 }
38 
39 void build(int curpos, int curl, int curr) {
40     if (curl > curr) return;
41     if (curl == curr) {
42         segt[curpos].val = a[curl];
43         segt[curpos].pos = curl;
44         return;
45     }
46     int mid = curl + curr >> 1;
47     build(lson, curl, mid); build(rson, mid + 1, curr);
48     maintain(curpos);
49 }
50 
51 Node query(int curpos, int curl, int curr, int ql, int qr) {
52     if (ql <= curl && curr <= qr) return segt[curpos];
53     int mid = curl + curr >> 1;
54     Node minn = Node(1e9 + 7, 1);
55     if (ql <= mid) {
56         Node res = query(lson, curl, mid, ql, qr);
57         if (res.val < minn.val) {
58             minn.val = res.val, minn.pos = res.pos;
59         }
60     }
61     if (qr > mid) {
62         Node res = query(rson, mid + 1, curr, ql, qr);
63         if (res.val < minn.val) {
64             minn.val = res.val, minn.pos = res.pos;
65         }
66     }
67     maintain(curpos);
68     return minn;
69 }
70 
71 ll solve(int l, int r) {
72     if (l > r) return 0LL;
73     if (l == r) {
74         ans[l] = a[l];
75         return a[l];
76     }
77     Node minn = query(1, 1, n, l, r);
78     ll sum1 = solve(l, minn.pos - 1), sum2 = solve(minn.pos + 1, r);
79     if (1LL * (r - minn.pos + 1) * minn.val + minn.val + sum1 > 1LL * (minn.pos - l + 1) * minn.val + minn.val + sum2) {
80         for (int i = minn.pos; i <= r; i++) ans[i] = minn.val;
81         return 1LL * (r - minn.pos - 1 + 1) * minn.val + minn.val + sum1;
82     } else {
83         for (int i = l; i <= minn.pos; i++) ans[i] = minn.val;
84         return 1LL * (minn.pos - 1 - l + 1) * minn.val + minn.val + sum2;
85     }
86 }
87 
88 int main() {
89     scanf("%d", &n);
90     for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
91     build(1, 1, n);
92     solve(1, n);
93     for (int i = 1; i <= n; i++) printf("%lld ", ans[i]);
94     puts("");
95     return 0;
96 }
View Code
原文地址:https://www.cnblogs.com/JHSeng/p/12358750.html