文章目录
Codeforces Round #650 (Div. 3)
D. Task On The Board
题意: 给定一个字符串,要求从字符串内一些字符,使得这些字符重新排列,满足b数组。b数组为:b[i]为所有重新排列后的字符内比i字符大的字符的位置的累加和。
题解: 如果b[i] = 0, 则表示该字符为最大的字符,那么我就把最大的字符填进去。然后所有字符的b数组都重新更新,因为所有字符都比i字符串小,意为删去这个字符。重新更新后,再次找到b[i] = 0的位置,不断迭代。
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1300;
typedef long long LL;
char str[70];
LL b[MAXN], num[30], vis[MAXN], T, m;
char ans[MAXN];
void init() {
memset(str, '\0', sizeof(str));
memset(num, 0, sizeof(num));
memset(ans, '\0', sizeof(ans));
}
int main() {
cin >> T;
while (T--) {
init();
cin >> str + 1;
int n = strlen(str + 1);
for (int i = 1; i <= n + 10; i++)
vis[i] = false, b[i] = 0;
cin >> m;
for (int i = 1; i <= m; i++) cin >> b[i];
for (int i = 1; i <= n; i++) num[str[i] - 'a' + 1]++;
int have = 0;
int top = 26;
int k = top;
int times = 1;
while (1) {
int zero = 0;
for (int i = 1; i <= m; i++) {
if (!vis[i] && b[i] == 0) // 找到b为0的数目
zero++;
}
for (int i = top; i >= 1; i--)
if (num[i] >= zero) { // 填为当前的字符
k = i;
break;
}
for (int i = 1; i <= m; i++) {
if (!vis[i] && b[i] == 0) {
ans[i] = char('a' + k - 1);
vis[i] = times;
}
}
for (int i = 1; i <= m; i++) {
if (vis[i] == times && b[i] == 0) {
have++;
for (int j = 1; j <= m; j++) {
if (b[j]) b[j] -= fabs(i - j);
}
}
}
times++;
top = k - 1;
if (have == m)
break;
}
for (int i = 1; i <= m; i++)
cout << ans[i];
cout << endl;
}
return 0;
}
E. Necklace Assembly
题意: 给你一个字符串,你从中挑选一些任意排序让它们成为一个环,使得这个环朝一个方向转k下,与原来看起来一样,找到你能够满足这个条件的可以挑选的最多的字符数量。
题解: 可以选择的循环为k的因子,因此首先枚举出k的所有因子。然后去二分是否能够构成环,check的时候贪心判断即可。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, m, T, k, cnt[30];
bool check(int each, int jie) {
for (int i = 0; i < 26; ++i) {
each -= cnt[i] / jie;
if (each <= 0)
return true;
}
return false;
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> T;
while(T--) {
memset(cnt, 0, sizeof cnt);
cin >> n >> k;
string s;
cin >> s;
for (int i = 0; i < s.size(); ++i) cnt[s[i] - 'a']++;
vector<int> fac;
for (int i = 1; i <= k / i; ++i) {
if (k % i == 0) {
fac.push_back(i);
if (k / i != i) fac.push_back(k / i);
}
}
int res = 1;
for (int i = 0; i < 26; ++i)
if (cnt[i] >= k) res = max(res, cnt[i]);
for (auto &each:fac) {
int l = 1, r = n / each;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (check(each, mid)) l = mid;
else r = mid - 1;
}
if (l * each <= n) res = max(res, l * each);
}
cout << res << '\n';
}
return 0;
}
F1. Flying Sort (Easy Version)
题意:
题解: 直接求最长上升子序列就行,然后n-最长上升子序列长度
代码:
F2. Flying Sort (Hard Version)
题意:
题解: 思维。
代码:
#include <bits/stdc++.h>
using namespace std;
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
return x * f;
}
const int N = 2e5 + 5;
int f[N], a[N], b[N], cnt[N], tot[N], fir[N], las[N];
int main(){
int i, j, x, n, m, T, ans;
T = read();
while(T--){
n = read(); ans = 0;
for(i = 1; i <= n; i++) a[i] = b[i] = read();
sort(b + 1, b + i);
m = unique(b + 1, b + n + 1) - b - 1;
for(i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + m + 1, a[i]) - b, cnt[a[i]]++;
for(i = 1; i <= n; i++){
x = a[i];
if(tot[x - 1] == cnt[x - 1]) f[i] = max(f[i], f[fir[x - 1]] + tot[x - 1]);
if(las[x]) f[i] = max(f[i], f[las[x]] + 1);
if(las[x - 1]) f[i] = max(f[i], tot[x - 1] + 1);
f[i] = max(f[i], 1);
ans = max(ans, f[i]);
las[x] = i;
if(!fir[x]) fir[x] = i;
tot[x]++;
}
printf("%d\n", n - ans);
for(i = 1; i <= n; i++) cnt[i] = tot[i] = f[i] = fir[i] = las[i] = 0;
}
return 0;
}