2023/03/08刷题
C. Alphabetic Removals
链接
这个题先找到需要去除的k个字符,然后再打印的时候去除这些字符就可以了
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long
#define yes cout<<"YES"<<'\n'
#define no cout<<"NO"<<'\n'
using namespace std;
int st[30];
bool flag[4 * 100000 + 5];
signed main () {
int n, k;
cin >> n >> k;
string s;
cin >> s;
for (int i = 0; i < s.size(); i++) {
st[s[i] - 'a']++;//统计每种字符出现的个数
}
int j = 0;
int res = 0;
for (j = 0; j < 26; j++) {//这个循环是判断k个字符到哪一个之母结束
if (res + st[j] >= k) {
st[j] = k - res;//并且把最后那个a[j]改成所需要的字符的个数
break;
} else {
res = res + st[j];
}
}
for (int i = 0; i < s.size(); i++) {//这个循环个每个字符打上flag,flag==true不会被打印
if (s[i] - 'a' <= j) {
if (st[s[i] - 'a'] > 0) {//当st[i]大于0的时候才删除标记这个字符
st[s[i] - 'a']--;
k--;
flag[i] = true;
} else {
continue;//否则判断下一个字符
}
if (k == 0) {//当k==0的时候退出循环
break;
}
}
}
for (int i = 0; i < s.size(); i++) {//当flag[i]==false的时候打印字符
if (flag[i] == false) {
cout << s[i];
}
}
return 0;
}
C. Differential Sorting
链接
这个题注意一下x<y<z这个条件,所以倒数第一个和倒数第二个是没有办法构造的所以他们必须一开始就应该是非递减的.然后我们构造后面的数可以发现倒数第一个数是最大的而当前构造的数的前面的那个数肯定是最小的,我们每次让这个最小的数减去最大的倒数第一个数,判断是不是比当前构造的前面的那个数大如果比它大就继续构造否则打印-1
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long
#define yes cout<<"YES"<<'\n'
#define no cout<<"NO"<<'\n'
using namespace std;
struct data {
int x, y, z;
};
const int N = 200008;
int a[N];
void solve() {
int n;
scanf("%lld", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
}
vector <struct data> res;
if (a[n - 1] <= a[n]) {//先判断最后两个
struct data temp;
for (int i = n - 2; i >= 1; i--) {//从倒数第三个向前构造
if (a[i] <= a[i + 1]) {//如果不需要构造直接contine
continue;
} else {//每次让这个数前面的那个减去倒数第一个来构造新的数
if (a[i + 1] - a[n] <= a[i + 1]) {//如果构造出来的数小于等于a[i]
temp.x = i;
temp.y = i + 1;
temp.z = n;
res.push_back(temp);//将索引放入数组
a[i] = a[i + 1] - a[n];//更改a[i]的值
} else {//否则无法构造,打印-1
cout << -1 << '\n';
return;
}
}
}
} else {//倒数两个数不满足条件,打印-1
cout << -1 << '\n';
return;
}
cout << res.size() << '\n';//最后打印所有的索引
for (int i = 0; i < res.size(); i++) {
cout << res[i].x << ' ' << res[i].y << ' ' << res[i].z << ' ' << '\n';
}
}
signed main () {
int t;
cin >> t;
while (t) {
solve();
t--;
}
return 0;
}
D. Divisibility by 2^n
链接
这个题也不会写,看了题解才会,我们要满足n个2相乘对吧,所以我们先统计原来有已经有多少个2了,然后看一下在合理的区间之内每个i可以提供多少个2,然后贪心的取2就可以了,直到满足或者不成立
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long
#define yes cout<<"YES"<<'\n'
#define no cout<<"NO"<<'\n'
using namespace std;
const int N = 2 * 100000 + 5;
signed main() {
int a[N] = {0};
int st[N] = {0};
int t;
scanf("%lld", &t);
while (t--) {
memset(st, 0, sizeof st);//初始化
int n;
scanf("%lld", &n);
int ans = 0;
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
int temp = i;
while (temp % 2 == 0) {//计算每个i有几个2因子
st[i]++;
temp = temp / 2;
}
temp = a[i];
while (temp % 2 == 0) {//计算每个a[i]有几个2因子用ans记录
ans++;
temp = temp / 2;
}
}
if (ans >= n) {//让ans大于n的时候就不需要再乘以i了所以是0
cout << 0 << '\n';
} else {
int res = 0;
int x = n - ans;//还需要多少个2相乘
sort(st + 1, st + n + 1);//对st[i]所保存2的个数进行排序
for (int i = n; i >= 1; i--) {//贪心的取
if (x - st[i] >= 0 && st[i] != 0) {//如果st[i]不为0,并且x - st[i] >= 0
x = x - st[i];//让x减去st[i]
res++;//让答案加1
}
if (x == 0) {//当x==0的时候跳出循环,或者等待循环结束
break;
}
}
if (x == 0) {//当x==0打印res
cout << res << '\n';
} else {//否则打印-1
cout << -1 << '\n';
}
}
}
return 0;
}