Codeforces Round #650 (Div. 3)
D. Task On The Board
题目大意:
想法:
我们容易想到我们每次按照字符的大小 从大往小去放字符,因为这样可以确保后面放的字符对之前放的字符没有影响。
换句话说:我们每选取了一个“大”的字符 它都会对它之后选取的字符造成影响(因为后面选取的都是“小”的)。也就是说每选取了一个字符,我们需要去看它确定我们后续需要选取的字符是什么(同一轮确定的字符我们要确保它们之间没有影响)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> #define ll long long #define ull unsigned long long #define ls nod<<1 #define rs (nod<<1)+1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define INF 0x3f3f3f3f #define max(a, b) (a>b?a:b) #define min(a, b) (a<b?a:b) const double eps = 1e-8; const int N = 2e6 + 10; const ll MOD = 998244353; const int mlog=20; int sgn(double a) { return a < -eps ? -1 : a < eps ? 0 : 1; } using namespace std; char s[100]; int b[100],vis[2000],num[50],ans[100]; int main() { int t; scanf("%d",&t); while (t--) { int n; scanf("%s %d",s+1,&n); for (int i = 1;i <= n;i++) { scanf("%d",&b[i]); vis[i] = 0; } for (int i = 0;i < 26;i++) num[i] = 0; for (int i = 1;i <= strlen(s+1);i++) { num[s[i]-'a']++; } vector<int> vec; int m = n; int now = 25; while (m) { int cnt = 0; vector<int> pos; for (int i = 1;i <= n;i++) { if (vis[i]) continue; int sum = 0; for (auto &to:vec) sum += abs(to-i); if (sum == b[i]) pos.push_back(i); } for (auto &to:pos) { vis[to] = true; cnt++; vec.push_back(to); } while (num[now] < cnt) now--; m -= cnt; for (auto &to:pos) ans[to] = (char) (now + 'a'); now--; } for (int i = 1;i <= n;i++) printf("%c",ans[i]); printf("\n"); } return 0; }
E. Necklace Assembly
题目大意:
想法:
首先我们应该想到 k 的因数应该都是满足的 因为是成倍的增长。
然后我们可以发现字符串
s[1] -> s[j + 1]
s[2] -> s[j + 2]
s[3] -> s[j + 3]
....
s[j - 1] -> s[2 * j - 1]
所以我们可以考虑字符串分成的段数,每段有 j 个字符,这样字符串的长度 = 每段的字符 * 分成的段数。
并且字符串分成的段数是符合二分的性质的,可以考虑二分。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> #define ll long long #define ull unsigned long long #define ls nod<<1 #define rs (nod<<1)+1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define INF 0x3f3f3f3f #define max(a, b) (a>b?a:b) #define min(a, b) (a<b?a:b) const double eps = 1e-8; const int N = 2e6 + 10; const ll MOD = 998244353; const int mlog=20; int sgn(double a) { return a < -eps ? -1 : a < eps ? 0 : 1; } using namespace std; char s[2010]; int num[30]; bool check(int mid,int v) { for (int i = 0;i <= 25;i++) { mid -= num[i] / v; if (mid <= 0) return true; } return false; } int main() { int t; scanf("%d",&t); while (t--) { int n,k; scanf("%d%d",&n,&k); scanf("%s",s+1); for (int i = 0;i <= 26;i++) num[i] = 0; for (int i = 1;i <= n;i++) { num[s[i]-'a']++; } int ans = 0; for (int i = 0;i <= 25;i++) { ans = max(ans,num[i]); } vector<int> vec; for (int i = 2;i <= k;i++) { if (k % i == 0) vec.pb(i); } for (auto &v:vec) { int l = 1,r = n / v; while (l <= r) { int mid = (l + r) >> 1; if (check(v,mid)) { ans = max(ans,mid*v); l = mid + 1; } else r = mid - 1; } } printf("%d\n",ans); } return 0; }
F1. Flying Sort (Easy Version)
题目大意:
想法:
首先数组a[i]的范围很大,我们需要先对它进行离散化,得到一个 1~n 的数组
然后我们可以发现 我们可以把问题转化为找到一组最长的不需要操作的序列 (因为这些序列不需要调整,其他的调整就可以了)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> #define ll long long #define ull unsigned long long #define ls nod<<1 #define rs (nod<<1)+1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define INF 0x3f3f3f3f #define max(a, b) (a>b?a:b) #define min(a, b) (a<b?a:b) const double eps = 1e-8; const int maxn = 1e4 + 10; const ll MOD = 998244353; const int mlog=20; int sgn(double a) { return a < -eps ? -1 : a < eps ? 0 : 1; } using namespace std; int a[maxn],s[maxn]; int dp[maxn]; int main() { ios::sync_with_stdio(false); int t; cin >> t; while (t--) { int n; cin >> n; for (int i = 1;i <= n;i++) { cin >> a[i]; s[i] = a[i]; dp[i] = 0; } sort(s+1,s+1+n); for (int i = 1;i <= n;i++) { a[i] = lower_bound(s+1,s+1+n,a[i]) - s; } int Max = 1; for (int i = 1;i <= n;i++) { dp[a[i]] = dp[a[i]-1]+1; Max = max(Max,dp[a[i]]); } cout << n - Max << endl; } return 0; }