Codeforces Round 898 (Div. 4)
Codeforces Round 898 (Div. 4)
A. Short Sort
解题思路:
遍历所有交换情况,看是否有\(abc\).
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
const int M = 2 * M;
typedef pair<int, int> pii;
#define fi first
#define se second
int n, m, k;
void solve()
{
string s;
cin >> s;
string a = s;
swap(a[0], a[1]);
string b = s;
swap(b[0], b[2]);
string c = s;
swap(c[1], c[2]);
string t = "abc";
if (s == t || a == t || b == t || c == t)
{
puts("YES");
}
else
{
puts("NO");
}
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--)
{
solve();
}
return 0;
}
B. Good Kid
解题思路:
将最小的数字加一.
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
const int M = 2 * M;
typedef pair<int, int> pii;
#define fi first
#define se second
int n, m, k;
void solve()
{
scanf("%d", &n);
vector<int> a(n + 1);
int idx = 0;
int res = 12312;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
if (a[i] < res)
{
res = a[i];
idx = i;
}
}
a[idx]++;
ll ans = 1;
for (int i = 1; i <= n; i++)
{
ans *= (ll)a[i];
}
printf("%lld\n", ans);
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--)
{
solve();
}
return 0;
}
C. Target Practice
解题思路:
由于图是固定的,暴力判断每个击中的点属于哪一类即可。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
const int M = 2 * M;
typedef pair<int, int> pii;
#define fi first
#define se second
int n, m, k;
char g[100][100];
void solve()
{
for (int i = 1; i <= 10; i++)
{
scanf("%s", g[i] + 1);
}
n = 10;
ll ans = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (g[i][j] == 'X')
{
if (i == 1 || i == 10)
{
ans += 1;
}
else if (i == 2 || i == 9)
{
if (j == 1 || j == 10)
{
ans += 1;
}
else
{
ans += 2;
}
}
else if (i == 3 || i == 8)
{
if (j == 1 || j == 10)
{
ans += 1;
}
else if (j == 2 || j == 9)
{
ans += 2;
}
else
{
ans += 3;
}
}
else if (i == 4 || i == 7)
{
if (j == 1 || j == 10)
{
ans += 1;
}
else if (j == 2 || j == 9)
{
ans += 2;
}
else if (j == 3 || j == 8)
{
ans += 3;
}
else
{
ans += 4;
}
}
else if (i == 5 || i == 6)
{
if (j == 1 || j == 10)
{
ans += 1;
}
else if (j == 2 || j == 9)
{
ans += 2;
}
else if (j == 3 || j == 8)
{
ans += 3;
}
else if (j == 4 || j == 7)
{
ans += 4;
}
else
{
ans += 5;
}
}
}
}
}
printf("%lld\n", ans);
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--)
{
solve();
}
return 0;
}
D. 1D Eraser
解题思路:
从左往右遍历,遇到一个\(B\)就以他为起点向右染白即可。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
const int M = 2 * M;
typedef pair<int, int> pii;
#define fi first
#define se second
int n, m, k;
void solve()
{
scanf("%d %d", &n, &k);
string s;
cin >> s;
int cnt = 0;
for (int i = 0; i < n; i++)
{
if (s[i] == 'B')
{
cnt++;
int j = 0;
for (j = i; j <= i + k - 1; j++)
{
s[i] = 'W';
}
j--;
i = j;
}
}
printf("%d\n", cnt);
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--)
{
solve();
}
return 0;
}
E. Building an Aquarium
解题思路:
二分高度,暴力判断。
注意本题二分边界,最小取到1。
由于答案上界为\(2\times 10^9\),\(n = 1,a[1] = 10^9,x = 10^9\)。
右边界也别取太大,如\(10^{18}\),二分过程会爆\(long \ long\)。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
const int M = 2 * M;
typedef pair<int, int> pii;
#define fi first
#define se second
int n, m, k;
void solve()
{
scanf("%d %d", &n, &k);
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
}
ll l = 1;
ll r = 3e9;
auto check = [&](ll h)
{
ll sum = 0;
for (int i = 1; i <= n; i++)
{
sum += max(0ll, h - a[i]);
}
if (sum > k)
{
return false;
}
else
{
return true;
}
};
while (l + 1 < r)
{
ll mid = l + r >> 1;
if (check(mid))
{
l = mid;
}
else
{
r = mid;
}
}
printf("%lld\n", l);
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--)
{
solve();
}
return 0;
}
F. Money Trees
解题思路:
类似滑动窗口。
从左往右遍历,在线记录以\(i\)为最后一个元素,向左最长可以选择多少元素。
用前缀和计算当前最大区间和。
若区间和大于限制,那么从左端点开始一个个删去,直至区间和合法。此时区间长度就是以第\(i\)个元素为结尾的最长区间。
全局答案就是所有最长区间中的最大值。
注意:左右端点可以相等。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
const int M = 2 * M;
typedef pair<int, int> pii;
#define fi first
#define se second
int n, m, k;
void solve()
{
scanf("%d %d", &n, &k);
vector<int> a(n + 1), h(n + 1), b(n + 1);
vector<ll> s(n + 1);
vector<pii> v;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
s[i] = a[i] + s[i - 1];
}
for (int i = 1; i <= n; i++)
{
scanf("%d", &h[i]);
}
ll ans = 0;
int idx = 0;
for (int i = 1; i <= n; i++)
{
if (i == 1)
{
b[i] = 0;
}
else if (h[i - 1] % h[i] == 0)
{
b[i] = b[i - 1] + 1;
}
else
{
b[i] = 0;
// continue;
}
int l = max(i - b[i], idx);
int r = i;
ll res = s[r] - s[l - 1];
if (res <= k)
{
// cout << i << ' ' << (r - l + 1) << endl;
ans = max(ans, r - l + 1ll);
}
else
{
while (res > k)
{
res -= a[l];
l++;
}
idx = l;
ans = max(ans, r - l + 1ll);
}
}
printf("%lld\n", ans);
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--)
{
solve();
}
return 0;
}
G .ABBC or BACB
解题思路:
我们可以将连续的\(A\)看成\(A\)块。
我们发现,一个\(B\)无论在\(A\)块的左边还是右边,都可以对整个\(A\)块进行连续操作,此时对答案的贡献就是块中\(A\)的个数\(res\)。
所以,我们统计\(A\)块的数量\(cnt_a\),同时统计与\(A\)块相邻的\(B\)的数量\(cnt_b\)。
如果\(cnt_b >= cnt_a\),那么答案就是\(res\).
否则,答案就是\(res-最小的A块中的A的数量\)。因为\(A\)块就是由\(B\)分割而来,\(min(cnt_b) = cnt_a - 1\)。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
const int M = 2 * M;
typedef pair<int, int> pii;
#define fi first
#define se second
int n, m, k;
void solve()
{
string s;
cin >> s;
n = s.size();
s = ' ' + s;
int ans = 0;
int cnt = 0;
int res = 0;
vector<int> v;
for (int i = 1; i <= n; i++)
{
char c = s[i];
if (c == 'A')
{
cnt++;
}
else
{
if (s[i - 1] == 'A' || s[i + 1] == 'A')
{
res++;
}
if (cnt)
{
v.push_back(cnt);
ans += cnt;
}
cnt = 0;
}
}
if (cnt)
{
v.push_back(cnt);
ans += cnt;
}
sort(v.begin(), v.end());
if (res < v.size())
{
if (!v.empty())
{
ans -= v[0];
}
}
printf("%d\n", ans);
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--)
{
solve();
}
return 0;
}
H. Mad City
解题思路:
首先,如果二者起点一样肯定寄。
\(n\)个点,\(n\)条边,图中一定有且仅有一个环。
否则如果\(b\)在环上,一定无敌。
如果\(b\)不在环上,一定要到环上才能永久兜圈子无敌,所以他要最快到环上。
所以,\(a\)要做的就是堵到\(b\)到环上的那个点。大家一起动,如果\(a\)能够快一步到那个点,那么\(b\)就无法永久不被抓到。
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int,int> pii;
#define fi
#define se
void solve()
{
int n,a,b;
scanf("%d %d %d",&n,&a,&b);
vector<vector<int>> adj(n + 10);
for(int i = 1;i<=n;i++)
{
int x,y;
scanf("%d %d",&x,&y);
adj[x].push_back(y);
adj[y].push_back(x);
}
vector<bool> st(n + 1),isc(n + 1);
vector<int> ver;
int tag = 0;
auto dfs =[&](auto self,int u,int fa) -> void
{
// cout<<u<<' ';
st[u] = true;
for(auto v : adj[u])
{
if(v == fa)
{
continue;
}
if(st[v])
{
if(!isc[v])
{
ver.push_back(v);
tag = v;
isc[u] = true;
}
continue;
}
self(self,v,u);
if(isc[v])
{
isc[u] = true;
ver.push_back(v);
}
if(tag == u)
{
isc[u] = false;
}
}
};
dfs(dfs,1,-1);
vector<int> dist(n + 1,-1);
auto bfs =[&](int x) -> int
{
queue<int> q;
q.push(x);
dist[x] = 0;
if(isc[x])
{
return x;
}
while(q.size())
{
auto u = q.front();
q.pop();
for(auto v : adj[u])
{
if(dist[v] != -1)
{
continue;
}
if(isc[v] || v == tag)
{
dist[v] = dist[u] + 1;
return v;
}
dist[v] = dist[u] + 1;
q.push(v);
}
}
};
auto bfs1 =[&](int s,int e) -> int
{
vector<int> d(n + 1,-1);
queue<int> q;
q.push(s);
d[s] = 0;
if(s == e)
{
return 0;
}
while(q.size())
{
auto u = q.front();
// cout<<u<<endl;
q.pop();
for(auto v : adj[u])
{
if(d[v] != -1)
{
continue;
}
if(v == e)
{
return d[u] + 1;
}
d[v] = d[u] + 1;
q.push(v);
}
}
};
if(a == b)
{
puts("NO");
return;
}
else if(b == tag || isc[b])
{
puts("YES");
return;
}
int t = bfs(b);
// cout<<t<<endl;
if(bfs1(a,t) <= dist[t])
{
puts("NO");
}
else
{
puts("YES");
}
}
int main()
{
int t = 1;
cin >> t;
while(t--)
{
solve();
}
return 0;
}