• Codeforces Round #650 (Div. 3) C、D、E


    题目
    题意: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;
    }
    
    
  • 相关阅读:
    webservice发布时一个奇怪的错误
    这样的正版验证
    谁在要你的命
    执行存储过程时候的一个非常奇怪的性能问题
    比尔·盖茨在哈佛大学毕业典礼上的演讲
    接口与抽象类
    系统分析师.Net俱乐部QQ群
    Qt遍历图片文件
    Qt实现数组的乱序排列
    关于Outlook删除原邮箱邮件的解决办法
  • 原文地址:https://www.cnblogs.com/nonames/p/13167963.html
Copyright © 2020-2023  润新知