Codeforces Round #645 (Div. 2)
A.Park Lighting
题意:给出n*m的矩阵,要用一个能放置在两个方格之间的边来点亮两个方格的灯照亮所有方格。
题解:没什么好说的,直接上代码。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1, M = 1; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define rep(i, x, y) for(i=x;i<=y;i++) 7 #define ref(i, x, y) for(i=x;i>=y;i--) 8 #define MEM(a, x) memset(a, x, sizeof(a)) 9 #define Sca(x) scanf("%d", &x) 10 #define Scl(x) scanf("%lld", &x) 11 #define Scf(x) scanf("%f", &x) 12 #define Sclf(x) scanf("%lf", &x) 13 14 int T, n, m; 15 bool vis[N]; 16 17 int main() 18 { 19 cin >> T; 20 while (T--) { 21 cin >> n >> m; 22 cout << (n * m + 1) / 2 << endl; 23 } 24 return 0; 25 }
B.Maria Breaks the Self-isolation
题意:建议大家提升英文水平(我忘了)
题解:直接上代码。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1e5+5, M = 1; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define rep(i, x, y) for(i=x;i<=y;i++) 7 #define ref(i, x, y) for(i=x;i>=y;i--) 8 #define MEM(a, x) memset(a, x, sizeof(a)) 9 #define Sca(x) scanf("%d", &x) 10 #define Scl(x) scanf("%lld", &x) 11 #define Scf(x) scanf("%f", &x) 12 #define Sclf(x) scanf("%lf", &x) 13 14 int T, n, a[N], cnt[N]; 15 bool vis[N]; 16 17 int main() 18 { 19 cin >> T; 20 while (T--) { 21 cin >> n; 22 for (int i = 1; i <= n; i++) 23 Sca(a[i]); 24 sort(a+1, a+1+n); 25 int num = 0; 26 for (int i = 1; i <= n; i++) { 27 if (a[i] <= i) num = i; 28 } 29 cout << num + 1 << endl; 30 } 31 return 0; 32 }
C.Celex Update
题意:给出两个点的坐标,求从第一个点走到第二个点(只能向下或向右),走时加上方格中的数字,求最后得到有多少种不同的数字和。
题解:首先,格子中的数字是斜向下增加1的。由此可知,走¬型的路线,得到的数字和是最小的,走L型的路线,得到的数字和是最大的。并且从一条路径的某一处本是向右改为向下,会使得数字和+1。于是由此,我们可以从最小的路线上的数字和+1一直加到最大路线和,也就是说,答案是最大-最小+1。于是我们可以将原图化为下面的形式:
则可以求得公式: ans=Δx∗Δy + 1
(当然也可以暴力然后找规律)
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1, M = 1; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define rep(i, x, y) for(i=x;i<=y;i++) 7 #define ref(i, x, y) for(i=x;i>=y;i--) 8 #define MEM(a, x) memset(a, x, sizeof(a)) 9 #define Sca(x) scanf("%d", &x) 10 #define Scl(x) scanf("%lld", &x) 11 #define Scf(x) scanf("%f", &x) 12 #define Sclf(x) scanf("%lf", &x) 13 14 int T, n; 15 bool vis[N]; 16 17 int main() 18 { 19 cin >> T; 20 while (T--) { 21 int x1, x2, y1, y2; 22 scanf("%d%d%d%d", &x1, &y1, &x2, &y2); 23 ll x = x2 - x1, y = y2 - y1; 24 ll ans = x * y + 1; 25 cout << ans << endl; 26 } 27 return 0; 28 }
D.The Best Vacation
题意:不同的日月计法,一年有n个月,每个月ai天,每个月的第i天有i点幸福值,问在连续的k天中,能获得的最多的幸福值是多少。(可以不在同一年里)
题解:因为可以在不同的年中,所以我们可以在原本的n个月后再加上与原来一样的n个月,模拟成两年。然后思考,已经选取了连续的t个月,使得剩下的天数无论是在t个月的前一个月或是t个月的后一个月中,都无法完全覆盖整个月,这时选择向前去覆盖天数显然比向后去覆盖得到的幸福值要高。(CF上的题解好像有证明过程,如果我记得住会来补的)所以最优的策略一定是以某一个月结尾的。所以我们可以枚举2 *n个月,以这个月为结尾的幸福值,然后取最大值即可。(用二分来寻找)
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 2e5+5, M = 1; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define rep(i, x, y) for(i=x;i<=y;i++) 7 #define ref(i, x, y) for(i=x;i>=y;i--) 8 #define MEM(a, x) memset(a, x, sizeof(a)) 9 #define Sca(x) scanf("%d", &x) 10 #define Scl(x) scanf("%lld", &x) 11 #define Scf(x) scanf("%f", &x) 12 #define Sclf(x) scanf("%lf", &x) 13 #define lb lower_bound 14 15 int T, d[N << 1]; 16 ll SumDay[N << 1], SumNum[N << 1], n, x, ans; 17 bool vis[N]; 18 ll calc(ll l, ll r) 19 {return (r - l + 1) * l + (r - l + 1) * (r - l) / 2;} 20 21 int main() 22 { 23 cin >> n >> x; 24 int mx = 0; 25 for (int i = 1; i <= n; i++) { 26 Sca(d[i]); SumDay[i] = SumDay[i - 1] + d[i]; SumNum[i] = SumNum[i - 1] + calc(1, d[i]); 27 } 28 for (int i = n + 1; i <= 2 * n; i++) { 29 d[i] = d[i - n]; 30 SumDay[i] = SumDay[i - 1] + d[i - n]; SumNum[i] = SumNum[i - 1] + calc(1, d[i - n]); 31 } 32 for (int i = 2 * n; i >= 1; i--) { 33 if (SumDay[i] < x) break; 34 int l = 1, r = i; 35 while (l < r) { 36 int mid = l + r >> 1; 37 if (SumDay[i] - SumDay[mid] - x <= 0) r = mid; 38 else l = mid + 1; 39 } 40 // cout << "l = " << l << endl; 41 ll temp = SumNum[i] - SumNum[l]; 42 ll sx = x - (SumDay[i] - SumDay[l]); 43 if (sx) temp += calc(d[l] - sx + 1, d[l]); 44 ans = max(ans, temp); 45 } 46 cout << ans << endl; 47 return 0; 48 }