Codeforces Round #650 (Div. 3)

58 篇文章 0 订阅
13 篇文章 1 订阅

A. Short Substrings

题意:一个字符串 abac,然后把所有长度为2的子串加起来变成新串,abbaac,由 ab ba ac组成。现在给出新串,找出原串。

思路:按题目模拟就好了,没啥说的。

AC代码:

#include <bits/stdc++.h>
using namespace std;
 
 
int main()
{
    int t;
    cin>>t;
    while(t--){
        string s;
        cin>>s;
        cout<<s[0];
        for(int i = 1; i < s.size()-1 ; i += 2){
            cout<<s[i];
        }
        cout<<s[s.size()-1]<<endl;
    }
    return 0;
}

B. Even Array

题意:给定一个数组。有一种操作,可以交换任意两个数的位置。要求的数组奇偶交替出现。最少需要多少次操作。

思路:先统计一遍都多少个奇数不在位置上,和多少个偶数不在位置上。如果不相等,那么无解。反之,把他们放到对应的位置就好了。

AC代码:

#include <bits/stdc++.h>
using namespace std;
 
 
int main()
{
    int t;
    cin>>t;
    while(t--){
        int n;
        int a[5000];
        cin>>n;
        for(int i = 0 ; i < n ;i ++) cin>>a[i];
        //sort(a,a+n);
        int cnt = 0;
        int res = 0;
        int tt= 0 ;
        for(int i = 0 ; i < n ; i ++){
            cnt += a[i]%2;
            tt += i%2;
            if(i%2 == 1 &&  a[i]%2 == 0){
                res ++;
            }
        }
        if(cnt == tt){
            cout<<res<<endl;
        }else{
            cout<<-1<<endl;
        }
    }
    return 0;
}

C. Social Distance

题意:给定一个01串。需要保证两个相邻的1之间的距离大于k。求原串在不违背题意的情况下,还能插入多少个1。

思路:分情况。左边连续的0单独计数。右边连续的0单独计数。中间出现的连续的0单独计数。就完了。

AC代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
 
signed main(){
    int t;
    cin>>t;
    while(t--){
        int n,k;
        string s;
        cin>>n>>k>>s;
        int cnt = 0;
        int pre = 0;
        int res = 0;
        k ++;
        int flag = 0;
        for(int i = 0 ; i < n ; i ++){
            if(s[i] == '0'){
                cnt ++;
            }else{
                flag = 1;
                if(pre == 0){
                    res += max(0LL,(cnt)/k);
                }else{
                    res += max(0LL,(cnt-k+1)/k);
                }
                pre = 1;
                cnt = 0;
            }
        }
        res += max(0LL,(cnt)/k);
        if(!flag) res = max(1+max(0LL,(n-1)/k),res);
        cout<<res<<endl;
    }
    return 0;
}

D. Task On The Board

题意:给定s串,删除一些字符,重新组合,得到t串。根据t串,可以计算一个b数组。bi = sum(|j-i|) if tj > ti,也就是所有比i位置大的字符的位置差的和。现在给定s和b数组,求t串。

思路:首先肯定是找b数组为0的位置。因为0,就表示,没有比他更大的字符了。然后这些位置填上了字符之后,对于非0的位置,他们都是有贡献的。把这些贡献从b数组中减掉,就又会尝试新的0的位置。就循环模拟这个过程就好了。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#include <unordered_map>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e6+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N],c[N];
char res[N];
int cnt[30];
int now;
map<int,int> mp;

void fill_(){
    for(; now >= 0 ; now --)
        if(cnt[now] >= mp[0])
            break;
    if(now < 0) return;
    for(int i = 0 ; i < n ; i ++)
        if(a[i] == 0)
            res[i] = 'a'+now;
    for(int i = 0 ; i < n ; i ++){
        if(res[i] == 'a'+now){
            mp[0] --;
            a[i] = -1;
            for(int j = 0 ; j < n ; j ++){
                if(a[j] > 0){
                    mp[a[j]]--;
                    a[j] -= abs(j-i);
                    mp[a[j]]++;
                }
            }
        }
    }
    now --;
}

signed main(){
    cin>>t;
    while(t--){
        string s;
        cin>>s;
        memset(cnt,0,sizeof(cnt));
        for(int i = 0 ; i < s.size() ; i ++)  cnt[s[i]-'a']++;
        cin>>n;
        mp.clear();
        for(int i = 0 ; i < n ; i ++){
            cin>>a[i];
            mp[a[i]]++;
            res[i] = 0;
        }
        now = 25;
        while(mp[0])  fill_();
        res[n] = 0;
        cout<<res<<endl;

    }
    return 0;
}

E. Necklace Assembly

题意:给定一堆字符。然后选出len个,围成一圈。且以k为循环节。即每转动k次,这个圈看上去是一模一样的。给定k。求最大的len。

思路:以K为循环节。那么以K的因子k为循环节都可以。所以先枚举K的所有因子。然后对于每个循环节k,如果只由k个元素组成。那显然是可以的。但是要要枚举 2*k,可不可以,3*k可不可以,直到找到一个最大的 n*k 可行。那么对于循环节k。最大长度就是 n*k 。对所有枚举到的取max就好了。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#include <unordered_map>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 1e6+7;
int n,m,k,t = 1,cas = 1;
int a[N];
 
int check(int k,int cnt[]){
    int tmp = k;
    for(int j = 2 ;  ; j ++){
        int tt = 0;
        for(int i = 0 ; i < 26 ; i ++){
            tt += cnt[i]/j;
        }
        if(tt >= k){
            tmp = j*k;
        }else{
            return tmp;
        }
    }
}
 
signed main(){
    cin>>t;
    while(t--){
        int cnt[100]= {0};
        string s;
        cin>>n>>m>>s;
        for(int i = 0 ; i < n ; i ++){
            cnt[s[i]-'a'] ++;
        }
        sort(cnt,cnt+100);
        reverse(cnt,cnt+100);
        int res = 1;
        for(int i = 1 ; i <= m && i <= n; i ++){
            if(m%i == 0){
                res = max(res,check(i,cnt));
            }
        }
        cout<<res<<endl;
    }
    return 0;
}

F1. Flying Sort (Easy Version)

题意:一个数组,一次操作可以选择一个数,放到数组开头,或者放到末尾。问最少多少次操作可以使得数组有序。Easy版中所有元素各不相同。且数组长度 < 3000。

思路:考虑求不需要动的元素。先对a数组离散化,变成值域1-n的数组。然后不需要动的元素是差值为1的连续上升子序列。dp求这个最大长度就好了。其他的数都是要移动的。并且要移动一个数。至多只移动一次就好了。所以求出最长子序列长度,再用n一减就是答案了。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#include <unordered_map>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 1e6+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int dp[N];

signed main(){
    cin>>t;
    while(t--){
        cin>>n;
        for(int i = 0 ; i < n ; i ++) cin>>b[i],a[i]=b[i];
        sort(b,b+n);
        for(int i = 0 ; i <= n ; i ++) dp[i] = 0;
        for(int i = 0 ; i < n ; i ++) a[i] = lower_bound(b,b+n,a[i])-b+1;
        int res = 0;
        for(int i = 0 ; i < n ; i ++){
            dp[a[i]] = dp[a[i]-1]+1;
            res = max(res,dp[a[i]]);
        }
        cout<<n-res<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值