题目
题意:n张桌子排成一排,1字符代表该桌子有人,0字符代表空桌,相邻两个人之间的距离不能少于k。
给出一组字符数组表示当前n张桌子的状态(保证该状态符合题意),问n张桌子还能最多坐几人。
解法:以边界和‘1’为分界线,考虑每一段连续空桌数目可坐几人.
const int maxn = 2e5+9;
char s[maxn];
void solve(){
int n , k ;
cin >> n >> k;
scanf("%s" , s+1);
vector<int>v;
v.pb(0);
rep(i , 1 , n){
if(s[i] == '1'){
v.pb(i);
}
}
v.pb(n+1);
int ans = 0 ;
if(size(v) == 2){//如果没有1
ans = (n+k) / (k+1);//向上取整
if(!ans) ans++;
cout << ans << endl;
return ;
}
rep(i , 1 , size(v)-1){
int cnt = v[i] - v[i-1] - 1 ;
if(i != 1 && i != size(v)-1){//两边边界都为1。
ans += (cnt - k) / (k+1);
}else{
ans += cnt / (k+1);//一边边界为1.
}
}
cout << ans << endl;
}
D题意:给出一个小写字母字符串s,和一个长为n的数组b,问能否从s字符串挑选出n个字母组成一个字符串,该字符串满足:b[i] 等于比第i个字母大所有字符的距离之和。
解法:b[i]一定存在值为0,因为最大字母的b[i]=0,所以跟据最大字母值模拟往前推。
const int maxn = 50+9;
char s[maxn] , str[maxn];
int b[maxn];
int cnt[maxn];
int vis[maxn];
int n ;
void work(int x){
rep(i , 1 , n){
if(b[i]){
b[i] -= abs(i-x);
}
}
}
void solve(){
ME(vis , 0);
ME(cnt , 0);
scanf("%s" , s+1);
rep(i , 1 , strlen(s+1)){
cnt[s[i]-'a']++;//统计字母
}
cin >> n ;
rep(i , 1 , n){
cin >> b[i];
}
while(true){
int flag = 1 ;
vector<int>v;
rep(i , 1 , n){
if(!b[i] && !vis[i]){//找出当前所有0值
v.pb(i);
vis[i] = 1;
flag = 0;
}
}
int index ;
red(i , 25 , 0){//找一个最大字母
if(cnt[i]){
if(cnt[i] >= size(v)){//该字母个数需要大于0值个数
index = i ;
cnt[i] = 0;//销毁该字母
break;
}else{
cnt[i] = 0;//销毁
continue;
}
}
}
for(auto i : v){//修改所有比该字母的b[i]
work(i);
str[i] = index+'a' ;
}
if(flag) break;
}
rep(i , 1 , n){
cout << str[i] ;
}
cout << endl;
}
E题意:有一个n个字符的字符串,要求使用其中字符构造一个环(不必全部都用)。定义一个环是k美的:它转k次仍是原样。现在给你k,要求最长的k美环的长度.
解法:考虑k的因子,如果k的因子满足k美,那么一定也是k美,枚举k因子作为循环节,二分最大周期数,答案即为最大的循环节*周期数.
int n , m ;
char s[maxn];
int cnt[27];
bool check(int x , int y){
rep(i , 0 , 25){
y -= cnt[i] / x ;
}
return y <= 0;//可以构造x周期的y循环节环
}
void solve(){
int n , k ;
cin >> n >> k;
scanf("%s" , s+1);
ME(cnt , 0);
rep(i , 1 , n){
cnt[s[i]-'a']++;
}
int ans = 1 ;
rep(i , 1 , k){
if(k % i == 0){//枚举k因子,即循环节长度
int l = 1 , r = n ;//二分查找最大周期数
int mid = (l + r) >> 1 ;
if(check(mid , i)){//周期为mid,循环节长为i
l = mid+1;
}else{
r = mid-1 ;
}
}
ans = max(ans , r*i);
}
}
cout << ans << endl;
}
另一种思路
const int maxn = 20+9;
int cnt[maxn];
void solve(){
int n , k ;
cin >> n >> k ;
string s ;
cin >> s;
ME(cnt , 0);
rep(i , 0 , n-1){
cnt[s[i]-'a']++;
}
int ans = 0 ;
rep(i , 1 , n){//枚举长度
int nc = gcd(i , k);
int percyc = i / nc ;//循环节长度
rep(j , 0 , 25){
nc -= cnt[j] / percyc;//该字母能填充的循环节长
}
if(nc <= 0) ans = i ;//如果大于循环节长度就符合。
}
cout << ans << endl;
}