A Casimir’s String Solitaire
题目大意
给定一个字符串和两种操作
- 删除任意位置A和B
- 删除任意位置B和C
问能否将全部字母删除
题目大意
判断B数量是否等于A+C的数量即可
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
const int N = 200010, mod = 998244353;
int n, m, a[N];
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
{
string s;
cin >> s;
int a = 0, b = 0, c = 0;
for(int i = 0; i < s.size(); i++)
{
if(s[i] == 'A') a++;
else if(s[i] == 'B') b++;
else c++;
}
if(a + c == b) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
B Shifting Sort
题目大意
给定一个长度为n的数组,问能否通过对某一个区间的操作使他变成递增的,问操作的步骤,操作不超过n次
主要思路
先排序,遍历排序后数组,对于每一个数在原数组中找到对应的然后将它移动到该位置即可
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
const int N = 200010, mod = 998244353;
int n, m, a[N], b[N];
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
b[i] = a[i];
}
sort(a + 1, a + 1 + n);
vector<int> ans1, ans2, ans3;
for(int i = 1; i <= n; i++)
{
int t;
if(a[i] == b[i]) continue;
for(int j = i + 1; j <= n; j++)
{
if(a[i] == b[j])
{
ans1.push_back(i);
ans2.push_back(j);
ans3.push_back(j - i);
t = j;
break;
}
}
for(int j = t - 1; j >= i; j--)
{
b[j + 1] = b[j];
}
b[i] = a[i];
}
cout << ans1.size() << endl;
for(int i = 0; i < ans1.size(); i++)
{
cout << ans1[i] << ' ' << ans2[i] << ' ' << ans3[i] << endl;
}
}
return 0;
}
C Ticks
题目大意
每一个*都会往左上右上延申,且每一个点最小延申k,问这个图能否通过延申得到
主要思路
遍历每一个*,如果他能延申,就将延伸到最长的路径都标记,最后判断是不是所有 *都被标记即可
AC代码
(学jls的写法)
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
const int N = 110, mod = 998244353;
int n, m, k;
char mp[N][N];
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
{
cin >> n >> m >> k;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
cin >> mp[i][j];
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(mp[i][j] == '.') continue;
int d = 0;
while(i - d >= 1 && j - d >= 1 && j + d <= m && mp[i - d][j - d] != '.' && mp[i - d][j + d] != '.') d++;
d--;
if(d >= k)
{
for(int l = 0; l <= d; l++)
{
mp[i - l][j - l] = 'X';
mp[i - l][j + l] = 'X';
}
}
}
}
bool flag = true;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(mp[i][j] == '*') flag = false;
if(flag) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
D Productive Meeting
题目大意
给定一个长度为n的数组,每次你能任选两个数让他们同时-1,问最多的操作次数
主要思路
由于a[i]总和最大为1e5,我们定义一个优先队列,每次取最大的两个数让他们同时-1再放回优先队列中即可
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
const int N = 200010, mod = 998244353;
int n, m, a[N];
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
{
priority_queue<pair<int, int>> q;
vector<pair<int, int>> ans;
cin >> n;
for(int i = 1; i <= n; i++)
{
int x;
cin >> x;
if(x) q.push({x, i});
}
while(q.size() > 1)
{
auto [a1, pos1] = q.top();
q.pop();
auto [a2, pos2] = q.top();
q.pop();
ans.push_back({min(pos1, pos2), max(pos1, pos2)});
if(a1 > 1) q.push({a1 - 1, pos1});
if(a2 > 1) q.push({a2 - 1, pos2});
}
cout << ans.size() << endl;
for(auto i : ans)
{
cout << i.x << ' ' << i.y << endl;
}
}
return 0;
}
E1 Permutation Minimization by Deque
题目大意
给定一个长度为n的序列,每次往双端队列中插入一个数,问字典序最小的序列是什么
主要思路
比双端队列第一个数小就放前面,比第一个数大就放后面
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
const int N = 200010, mod = 998244353;
int n, m, a[N], b[N];
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
{
cin >> n;
deque<int> q;
for(int i = 1; i <= n; i++) cin >> a[i];
q.push_front(a[1]);
for(int i = 2; i <= n; i++)
{
if(a[i] >= q.front()) q.push_back(a[i]);
else q.push_front(a[i]);
}
for(auto i : q)
{
cout << i << ' ';
}
cout << endl;
}
return 0;
}
E2 Array Optimization by Deque
题目大意
给定一个长度为n的序列,每次往双端队列中插入一个数,问序列逆序对个数最小是多少
主要思路
考虑每一次放数时会生成的逆序对数量,加入当前序列中比放入的数x大的数的个数为cnt1,比放入的数x小的数的个数为cnt2,那么我们肯定选择生成逆序对最小的放法。
- cnt1 >= cnt2,x放在双端队列末尾
- 否则,x放在双端队列开头
接下来考虑如何判断双端队列中大于x和小于x的数的个数
我们先把输入的数组排序+离散化,然后每个数都有确定的下标,于是我们用树状数组维护每个数的出现次数即可,例如插入一个数x,我们在数组中二分查找到x的下标,在树状数组中+1即可
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
const int N = 200010, mod = 998244353;
int n, m, b[N];
int tr[N];
vector<int> a;
int lowbit(int x) // 返回末尾的1
{
return x & -x;
}
void add(int x, int c)
{
for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
int sum(int x)
{
int res = 0;
for(int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
int find(int x)
{
return lower_bound(a.begin(), a.end(), x) - a.begin();
}
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
{
a.clear();
int res = 0;
cin >> n;
for(int i = 0; i < n; i++)
{
int x;
cin >> x;
a.push_back(x), b[i] = x;
}
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
for(int i = 0; i < n; i++)
{
int t = find(b[i]) + 1;
int cnt1 = sum(a.size()) - sum(t);
int cnt2 = sum(t - 1);
if(cnt1 >= cnt2) res += cnt2;
else res += cnt1;
add(t, 1);
}
for(int i = 0; i < n; i++)
{
int t = find(b[i]) + 1;
add(t, -1);
}
cout << res << endl;
}
return 0;
}
F Array Stabilization (AND version)
题目大意
我们每次让该数组最后d位放到数组前面,也就是所有的i变成(i + d) % n,然后让变化后的数组每一个元素&变化前的数组,求该数组全0时的操作次数
主要思路
0不会对答案造成影响,我们只需判断每一位1需要多少次操作能变成0即可。
然后我们bfs遍历这个序列判断出每个点的最小步数, 求最小步数的最大值即可。
我们先把0放进队列,然后更新他能到的位置的最小值,如果该位置被更新然后再将该位置放进队列,相当于bfs的操作
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
typedef pair<int, int> P;
const int N = 1000010, mod = 998244353;
int n, m, k, a[N];
int dist[N];
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
{
memset(dist, 0x3f, sizeof(dist));
cin >> n >> k;
for(int i = 0; i < n; i++) cin >> a[i];
priority_queue<int, vector<int>, greater<int>> q;
for(int i = 0; i < n; i++)
{
if(!a[i])
{
q.push(i);
dist[i] = 0;
}
}
while(q.size())
{
int pos = q.top();
q.pop();
if(dist[pos] + 1 < dist[(pos + k) % n])
{
q.push((pos + k) % n);
dist[(pos + k) % n] = dist[pos] + 1;
}
}
int mx = 0;
for(int i = 0; i < n; i++)
{
mx = max(mx, dist[i]);
}
if(mx == 0x3f3f3f3f3f3f3f3f) cout << -1 << endl;
else cout << mx << endl;
}
return 0;
}
这篇博客介绍了ACasimir'sStringSolitaire问题的解决方案,涉及字符串删除操作的游戏策略。关键点在于判断B字符数量是否等于A和C的总和,提供了解题的AC代码示例。
656

被折叠的 条评论
为什么被折叠?



