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\n", ans); 50 } 51 return 0; 52 }
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\n", max(1, min(n, x + y + 1 - n)), min(x + y - 1, n)); 22 } 23 return 0; 24 }
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 }
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 }