B - Vlad and Candies
题意
给定一个数组,每次只能取最大的元素,要求每次取的相邻的元素不能相等,问能否取完
题解
我们知道,当最大值比最大值多2的时候,这个时候拿掉一个最大值,接下来就没得选了
当最大值比最大值的差距小于等于1的时候,我们可以这两个值轮流来拿,使得其依次变小,这时候我们就能同时使这些数来变小,到与其他数相同的时候我们还可以选择其他数来变小,这样循环下去,我们就能使所有的数一起变为0
Code
void solve(){
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
sort(a + 1, a + 1 + n);
reverse(a + 1, a + 1 + n);
if(n == 1){
if(a[1] == 1)
cout << "YES" << endl;
else
cout << "NO" << endl;
re;
}
if(a[1] - a[2] > 1)
cout << "NO" << Endl;
else
cout << "YES" << endl;
}
C - Get an Even String
题意
给定一个字符串,从中删除最小的字符数量满足下列条件:
- 字符串长度为偶数
- 对于所有的奇数 i ( 1 ≤ i ≤ n − 1 ) i(1\leq i \leq n-1) i(1≤i≤n−1),满足 a i = a i + 1 a_i=a_{i+1} ai=ai+1
题解
考虑删除字符串后,剩余字符串满足条件的最长长度
遍历字符串,如果出现相同的字符,就删除中间的
Code
string ss;
void solve(){
cin >> ss;
set<char> s;
int ans = 0;
for(auto i : ss){
if(s.count(i)){
ans += s.size() - 1;
s.clear();
}
else
s.insert(i);
}
cout << ans + s.size() << endl;
}
D - Maximum Product Strikes Back
题意
给定一个长度为 n n n的数组 a a a,其中 a ( a b s ( a ) ≤ 2 ) a(abs(a)\leq 2) a(abs(a)≤2),你可以删除数组的前缀和后缀,使其剩余子数组的乘积最大
问该怎么删除,其中空数组的乘积定义为1
题解
我们知道,当数组元素中出现0的时候显然是0的,所以我们以0为分隔,看其中的数的乘积是不是能够最大
同时我们知道,偶数个负数乘起来才是正数,而又因为数组元素的绝对值是 小于等于2的,也就是说只有出现2的时候,或者偶数个-2的时候,乘积才会增加
那么我们回过头来看这个已经被拿出来的这个子串。
如果里面的乘积是正的,那么我们直接看是否能更新答案;如果里面的乘积是负数,那么我们从左边找到第一个负数,从右边找到第一个负数,分别看看以这个数为分割点的左右两边是不是能更新答案
为什么要选第一个负数呢,首先乘积是负数说明我们现在出现了奇数个负数,我们去掉一个负数就可以使乘积变为正数;其次,如果选择下一个奇数的负数,也就是第三个负数,那么会漏掉很多数,显然不如只去掉一个负数来的乘积大
比赛的时候就只考虑了分隔负数后的一半的方向qwq
参考:https://zhuanlan.zhihu.com/p/491307345
Code
int n;
int a[N];
ll ans;
PII ans_id;
int cnt_fu(int l, int r){
int cnt = 0;
for (int i = l; i <= r; i ++)
if(a[i] < 0)
cnt++;
return cnt;
}
void update(int l, int r){
if(l > r)
return;
int two = 0;
for (int i = l; i <= r; i ++){
if(abs(a[i]) == 2)
two++;
}
if(two > ans){
ans_id = {l - 1, n - r};
ans = two;
}
}
void work(int l, int r){
int fu = cnt_fu(l, r);
if(fu % 2 == 0){
update(l, r);
}
else{
int id = l;
while(a[id] >= 0)
id++;
update(l, id - 1);
update(id + 1, r);
id = r;
while(a[id] >= 0)
id--;
update(l, id - 1);
update(id + 1, r);
}
}
void solve(){
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
int l = 0;
int r = 0;
ans = 0;
ans_id = {0, n};
for (int i = 1; i <= n; i++){
if(a[i] == 0){
work(l + 1, r);
l = i;
}
r++;
}
work(l + 1, r);
cout << ans_id.x << ' ' << ans_id.y << endl;
}
E - Matrix and Shifts
题意
给定一个n*n的01矩阵,可以多次执行下列四个操作
- 将第一行放到最后一行下面
- 将最后一行放到第一行上面
- 将第一列放到最后一列后面
- 将最后一列放到第一列前面
现在问经过多次操作后,和一个单位矩阵相比,最少可以有多少个不同的地方
题解
还是参考ygg:https://zhuanlan.zhihu.com/p/491307345
Code
int n;
char s[2010][2010];
void solve(){
cin >> n;
for (int i = 0; i < n; i++){
cin >> s[i];
}
int summ = 0;
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
if (s[i][j] == '1')
summ++;
}
}
int ans = 0;
for (int j = 0; j < n; j++){
int cnt = 0;
for (int i = 0; i < n; i++){
if (s[i][(i + j) % n] == '1')
cnt++;
}
ans = max(cnt, ans);
}
cout << summ - ans + n - ans << endl;
}
F2 - Promising String (hard version)
还是参考ygg,写的太好了https://zhuanlan.zhihu.com/p/491307345
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()
using namespace std;
using PII = pair<int, int>;
const int N = 5e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};
int T;
// +----
struct BIT
{
int tr[N];
int lb(int x){
return x & -x;
}
void init(int n){
for (int i = 0; i <= n + 2; i++){
tr[i] = 0;
}
}
void modify(int p, int v){
for(; p < N; p += lb(p)){
tr[p] += v;
}
}
int query(int p){
int res = 0;
for(; p; p -= lb(p)){
res += tr[p];
}
return res;
}
int query(int l, int r){
return query(r) - query(l - 1);
}
}tr[3];
int n;
string ss;
int a[N];
int s[N];
void solve(){
cin >> n;
cin >> ss;
ss = ' ' + ss;
s[0] = 0;
int minn = 0;
for (int i = 1; i <= n; i++){
a[i] = (ss[i] == '+' ? -1 : 1);
s[i] = s[i - 1] + a[i];
minn = min(minn, s[i]);
}
// cout << minn << endl;
for (int i = 0; i <= n; i++)
s[i] += (-minn + 1);
for (int i = 0; i < 3; i ++)
tr[i].init(n + (-minn + 1));
ll ans = 0;
for (int i = 0; i <= n; i++){ // 前缀和思想,我们要用pre[0]来构造答案
int m = s[i] % 3;
ans += tr[m].query(s[i]);
tr[m].modify(s[i], 1);
}
cout << ans << endl;
}
int main(){
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
T = 1;
cin >> T;
while(T--){
solve();
}
}