• 贪心+树状数组维护一下 Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) D


    http://codeforces.com/contest/724/problem/D

    题目大意:给你一个串,从串中挑选字符,挑选是有条件的,按照这个条件所挑选出来的字符集合sort一定是最后选择当中最小的。

    从pos=0开始挑选,每次挑选pos~pos+m-1这些位置中的字符,然后下一次再从之前挑选字符的位置开始的后面的m个中进行挑选。

    思路:先贪心,按照字典序,每次找到该范围区间内最小的字符,因为该字符一定是串中的一部分,所以必然会被挑选的,于是我们先把这个pos的字符放入集合,并且对挑选过的位置做上标记。按照之前的方法可以先得到了一个集合,但是该集合不一定是最小的,例如m=2的时候cbbadca你前面挑选的集合为baca,但是你会发现还有一个b,如果放入的话字典序会更小,所以我们先得到目前集合中最大的字符,令他为ch,再for一遍把比ch小的再给放进来就好了。

    说一下树状数组的作用,因为统计到末尾的时候,我不知道是直接结束还是再放入末尾区间内的某个字母,所以我利用树状数组统计了一下前面所有字符出现的次数,然后查询区间比末尾区间最小的字符串大的字符是否存在,如果存在就放入。

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 100000 + 5;
    int n, chlen;
    char ch[maxn];
    int tree[200 + 5];
    vector<char> v;
    char s[maxn];
    bool vis[maxn];
    
    void update(int x, int val = 1){
        for (int i = x; i <= 200; i += i & -i){
            tree[i] += val;
        }
    }
    
    int sum(int x){
        int ans = 0;
        for (int i = x; i > 0; i -= i & -i){
            ans += tree[i];
        }
        return ans;
    }
    ///①并不是越长越好 ②最短长度是已经确定了的③所选出来的一定要比最短的那个的字典序要小
    ///目标,长度短,字典序短
    void solve(){
        int pos = 0, slen = strlen(s);
        char minich = ch[pos];
        for (int i = pos + 1; i < n; i++){
            if(minich >=  ch[i]){minich = ch[i], pos = i;}
        }
        vis[pos] = true;
        v.pb(minich);
        while (pos < chlen){
            int minipos = pos + 1; minich = ch[minipos];
            for (int i = minipos + 1; i <= min(chlen, pos + n); i++){
                if (minich >= ch[i]){minich = ch[i], minipos = i;}
            }
            if (pos + n > chlen){
                int val = sum(200) - sum(minich);
                if (val == 0) break;
            }
            vis[minipos] = true;
            v.pb(minich);
            update(minich);
            pos = minipos;
        }
        sort(ALL(v));
        char maxch = v[v.size() - 1];
        for (int i = 0; i <= chlen; i++){
            if (!vis[i] && maxch > ch[i]){
                vis[i] = true; v.pb(ch[i]);
            }
        }
    }
    
    int main(){
        while (scanf("%d", &n) == 1){
            memset(vis, false, sizeof(vis));
            memset(tree, 0, sizeof(tree));
            memset(s, 0, sizeof(s));
            memset(ch, 0, sizeof(ch));
            scanf("%s", ch);
            chlen = strlen(ch);
            if (n > chlen) {printf("
    "); continue;}
            chlen--;
            int cnt = 0;
            for (int i = 2; i <= chlen; i += 2){
                s[cnt++] = ch[i];
            }
            solve();
            sort(ALL(v));
            for (int i = 0; i < v.size(); i++){
                printf("%c", v[i]);
            }
            printf("
    ");
            v.clear();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Visual Studio LightSwitch
    Android 虚拟机与真机调试配置
    点击手机 menu 硬件按钮后的显示及处理
    Windows Phone 7 真机调试
    Android 调试
    Android 新建项目 页面
    今天我的Windows Phone 7 HTC HD7 手机 升级 NoDo 了 分享一下经验
    Activity 之间调用与参数传递
    Android widget 组件
    解决 warning: found plain 'id' attribute; did you mean the new 'android:id' name? 问题
  • 原文地址:https://www.cnblogs.com/heimao5027/p/5945680.html
Copyright © 2020-2023  润新知