Educational Codeforces Round 82

A - Erasing Zeroes

给定01串,所有1连续,删0的最小次数
记录1的出现始末位置ft,1的总个sum数。输出t-f+1-sum

string s;
int t;
int main(){
    t=ird();
    while(t--){
        cin>>s;
        int len=s.length();
        int sum=0,f=0,t=-1;
        for(int i=0;i<len;i++){
            if(s[i]=='1'){
                sum++;
                if(s[0]!='1'&&f==0){
                    f=i;
                }
                t=i;
            }
        }
        cout<<t-f+1-sum<<endl;
    }
    return 0;
}

B - National Project

好坏天气gb周期出现,给定ngb,要求大于n的一半落在g内,其余任意。
找到g满足后,b需要的最小周期数mo。(如果tt/g无余数,mo减一)最后计算此时的天数,如果大于n就输出。小于n就要填满。即输出max(n,ans)

LL a[maxn];
int main(){
    int t=ird();
    while(t--){
        LL ans=0;
        LL n,g,b;
        n=ird();g=ird();b=ird();
        LL tt=n-n/2;
        LL mo=tt/g;
        if(tt%g==0)
            mo--;
        ans=tt+mo*b;
        cout<<max(n,ans)<<endl;
    }
    return 0;
}

C - Perfect Keyboard

给定小写字母字符串序列,要求按给定序列遍历时,相邻两字符在答案中也相邻的26个字符排列。
开vector,记录上一个位置,判断左右是否合法
细节处理注意(首字符连续),else if慎用!!!!(连wa4发o

string s;
int main(){
    int t=ird();
    while(t--){
        map<int,char> m;
        cin>>s;
        vector<char> v;
        int f=0;
        int tag=0;
        v.push_back(s[0]);
        m[s[0]]=1;
        int i=0;
        while(v[tag]==s[i+1]&&i<s.length()){
            i++;
        }
        for(;i<s.length()-1;i++){
            if(v.size()==1){
                v.push_back(s[i+1]);
                m[s[i+1]]=1;
                tag++;
            }
            else if(m[s[i+1]]==1){//出现过
                if(v[tag]==s[i+1])
                    continue;
                else if(v[tag-1]==s[i+1])
                    tag--;//右移
                else if(v[tag+1]==s[i+1])
                    tag++;//左移
                else{
                    f=1;
                    cout<<"NO"<<endl;
                    break;
                }
            }
            else if(m[s[i+1]]==0){//没出现过
                if(tag==0){//在头
                    v.insert(v.begin(),s[i+1]);
                    m[s[i+1]]=1;
                }
                else if(tag==v.size()-1){//在尾
                    v.push_back(s[i+1]);
                    tag++;
                    m[s[i+1]]=1;
                }
                else{
                    f=1;
                    cout<<"NO"<<endl;
                    break;
                }
            }
        }
        if(f==0){
            cout<<"YES"<<endl;
            for(int i=0;i<v.size();i++)
                cout<<v[i];
            for(int i=0;i<26;i++){
                char c='a'+i;
                if(m[c]==0)
                    cout<<c;
            }
            cout<<endl;
        }
    }
    return 0;
}

D. Fill The Bag

给定nm,n是需要恰好达到的数字大小,给定m个2的幂次的数字。合法操作:

  • 将数字加起来(不计贡献
  • 将am/2,分成两份(贡献+1

求最小贡献。

看到/2操作,还要相加刚好为n,想到转化为二进制,统计并记录下标到m,f(目标)中
贪心:从小到大遍历,m能消除的f中的1先减去(相当于操作1),不能减去的放进stack(取出时候要从大到小拿),每遇到一个多余的m就用他吧stack里的f全消除。

(wa了好多发获奖感言)注意在stack删除的时候每次贡献的值不是单纯和i相减,记录pre(最接近此时f现有值),贡献为pre-st.top()

LL n;
int mm;
int main(){
    int t=ird();
    while(t--){
        map<int,int> m,f;
        stack<int> st;
        n=lrd();
        mm=ird();
        int ans=0;
        int co;
        for(int i=1;i<=mm;i++){
            LL tt=ird();
            co=0;
            while(tt){
                co++;
                if(tt%2){
                    m[co]++;
                    break;
                }
                tt/=2;
            }
        }
        co=0;
        int maxx=0;
        while(n){
            co++;
            if(n%2){
                maxx=co;
                f[co]++;
            }
            n/=2;
        }
        for(int i=1;i<=80;i++){
            if(m[i]){
                if(f[i]){
                    m[i]--;
                    f[i]--;
                }
                if(!st.empty()&&m[i]){
                    int pre=i;
                    m[i]--;
                    while(!st.empty()){
                        ans+=pre-st.top();
                        pre=st.top();
                        st.pop();
                    }
                }
                m[i+1]+=m[i]/2;
                m[i]%=2;
            }
            if(f[i])
                st.push(i);
        }
        if(st.empty())
            cout<<ans<<endl;
        else
            cout<<-1<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值