Codeforces Round 920 (Div. 3)
Codeforces Round 920 (Div. 3)
A - Square
解题思路:
取左下角和右上角。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
void solve()
{
int x1 = 1e9;
int x2 = -1e8;
int y1 = 1e9;
int y2 = -1e8;
int x, y;
for (int i = 1; i <= 4; i++)
{
cin >> x >> y;
x1 = min(x, x1);
y1 = min(y, y1);
x2 = max(x, x2);
y2 = max(y, y2);
}
// cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
cout << (x2 - x1) * (y2 - y1) << endl;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
B - Arranging Cats
解题思路:
统计不匹配的\(1\)的数量。多删少添。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
void solve()
{
int n;
cin >> n;
string s, f;
cin >> s;
cin >> f;
ll a = 0;
ll b = 0;
for (int i = 0; i < n; i++)
{
if (s[i] == '1' && f[i] == '0')
{
a++;
}
if (s[i] == '0' && f[i] == '1')
{
b++;
}
}
if (a >= b)
{
cout << a << endl;
}
else
{
cout << b << endl;
}
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C - Sending Messages
解题思路:
对于每一步,要么直接冲,要么关机再开机,枚举即可。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
void solve()
{
ll n, f, a, b;
cin >> n >> f >> a >> b;
vector<int> m(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> m[i];
}
ll cur = 0;
for (int i = 1; i <= n; i++)
{
ll dist = m[i] - cur;
if (dist * a <= b)
{
f -= dist * a;
}
else
{
f -= b;
}
if (f <= 0)
{
puts("NO");
return;
}
cur = m[i];
}
puts("YES");
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
D - Very Different Array
解题思路:
对于每次选取,取\(a\)中最大最小和\(b\)中最大最小分别进行组合。取差最大的组。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
void solve()
{
ll n, m;
cin >> n >> m;
vector<ll> a(n + 1), b(m + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= m; i++)
{
cin >> b[i];
}
sort(a.begin() + 1, a.end());
sort(b.begin() + 1, b.end());
ll ans = 0;
int la = 1;
int ra = n;
int lb = 1;
int rb = m;
while (n--)
{
ll t1 = 0;
ll t2 = 0;
int ta = -1;
int tb = -1;
if (abs(a[la] - b[lb]) > abs(a[ra] - b[lb]))
{
t1 = abs(a[la] - b[lb]);
ta = 1;
}
else
{
t1 = abs(a[ra] - b[lb]);
ta = 0;
}
if (abs(a[la] - b[rb]) > abs(a[ra] - b[rb]))
{
t2 = abs(a[la] - b[rb]);
tb = 1;
}
else
{
t2 = abs(a[ra] - b[rb]);
tb = 0;
}
if (t1 > t2)
{
ans += t1;
if (ta)
{
la++;
lb++;
}
else
{
ra--;
lb++;
}
}
else
{
ans += t2;
if (tb)
{
la++;
rb--;
}
else
{
ra--;
rb--;
}
}
}
cout << ans << endl;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
E - Eat the Chip
解题思路:
如果开始就注定碰不到,那么就是平局。
若\(x\)差为奇数,那么就是\(B\)尽量寻求平局,\(A\)求胜。即\(B\)尽量往墙边跑。
若\(x\)差为偶数,那么就是\(A\)尽量寻求平局,\(B\)求胜。即\(A\)尽量往墙边跑。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
void solve()
{
ll h, w, xa, ya, xb, yb;
cin >> h >> w >> xa >> ya >> xb >> yb;
if (xa >= xb)
{
puts("Draw");
return;
}
else
{
if (abs(xa - xb) < abs(ya - yb))
{
puts("Draw");
return;
}
ll d = abs(xa - xb);
if (d & 1)
{
if (abs(ya - yb) > 1)
{
if (ya < yb)
{
ll t = w - yb;
d -= 2 * t;
// cout << abs(ya - yb) << ' ' << t << endl;
if (abs(ya - yb) > (d + 1) / 2)
{
puts("Draw");
return;
}
else
{
puts("Alice");
return;
}
}
else
{
ll t = yb - 1;
d -= 2 * t;
// cout << t << endl;
if (abs(ya - yb) > (d + 1) / 2)
{
// cout << 1 << endl;
puts("Draw");
return;
}
else
{
puts("Alice");
return;
}
}
}
else
{
puts("Alice");
return;
}
}
else
{
if (abs(ya - yb) >= 1)
{
if (ya < yb)
{
ll t = ya - 1;
d -= 2 * t;
if (abs(ya - yb) > (d) / 2)
{
puts("Draw");
return;
}
else
{
puts("Bob");
return;
}
}
else
{
ll t = w - ya;
d -= 2 * t;
if (abs(ya - yb) > (d) / 2)
{
puts("Draw");
return;
}
else
{
puts("Bob");
return;
}
}
}
else
{
puts("Bob");
return;
}
}
}
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
F - Sum of Progression
解题思路:
根号分治。
\(pre[d][i]:跳跃间隔为d时,从左到右到达第i位时的前缀和。\)
\(sum[d][i]:跳跃间隔为d时,从左到右到达第i位时的带权前缀和。权值为,当前位置为从左到右跳跃到的第几项。\)
\(pre[d][i] = \sum\limits_{idx = 1}^{\lceil\frac{i}{d}\rceil}a[i]\)
\(sum[d][i] = \sum\limits_{idx = 1}^{\lceil\frac{i}{d}\rceil} (idx \times a[i])\)
举例:
\(s = 4,d = 3,k = 3\)
\(a[4] + 2 * a[7] + 3 * a[10]\)
\(sum[3][1] = a[1]\)
\(sum[3][10] = a[1] + 2 * a[4] + 3 * a[7] + 4 * a[10]\)
\(sum[3][10] - sum[3][1] = 2 * a[4] + 3 * a[7] + 4 * a[10]\)
\(ans = sum[3][10] - sum[3][1] - 1 * (pre[3][10] - pre[3][1])\)
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
const int N = 1e5 + 10;
const int lim = sqrt(N);
void solve()
{
int n, q;
cin >> n >> q;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
vector<vector<ll>> sum(lim + 10, vector<ll>(n + 10)), pre(lim + 10, vector<ll>(n + 10));
for (int d = 1; d <= lim; d++)
{
for (int i = 1; i <= n; i++)
{
pre[d][i] = pre[d][max(i - d, 0)] + a[i];
sum[d][i] = sum[d][max(i - d, 0)] + a[i] * ((i + d - 1) / d);
}
}
while (q--)
{
ll s, d, k;
scanf("%lld %lld %lld", &s, &d, &k);
ll ans = 0;
if (d >= lim)
{
ll cnt = 1;
while (k--)
{
ans += cnt * a[s];
s += d;
cnt++;
}
}
else
{
int r = s + (k - 1) * d;
ans = sum[d][r] - sum[d][max(s - d, 0ll)] - ((s + d - 1) / d - 1) * (pre[d][r] - pre[d][max(s - d, 0ll)]);
}
cout << ans << ' ';
}
cout << endl;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号