10月30日Codeforces Round 905 (Div. 3)

B. Chemistry

题意: 删除k个元素后能否组成一个回文序列(可任意排列)

思路:计算有多少个奇数的字母,如果最后(n-k)剩偶数个,就看k次能不能把奇数减去;如果最后剩奇数个,看k次能不能把奇数减一个 减去,

收获:思路要想的深一步,不要想到就写,有可能写复杂了。多想一下,可以有更简洁的方法

void solve()
{
    int cntji=0,cntou=0;
    memset(a,0,sizeof a);
    cin>>n>>k>>s;
    for(int i = 0;i<n;i++)  a[s[i]-'a']++;

    for(int i = 0;i<=25;i++)
    {
        if(a[i]==0)continue;
        if(a[i]%2==1)cntji++;
        else cntou++;
    }

    if((n-k)%2==0)
    {
        if(k>=cntji)cout<<"Yes\n";
        else cout<<"No\n";
    }
    else
    {
        if(k>=cntji-1)cout<<"Yes\n";
        else cout<<"No\n";
    }
}

C. Raspberries

题意:对ai进行多少次加一操作,使得a1*a2*a3*an可被k整除

思路:对所有k暴力求解一次,再特判k=4的时候

收获,可以注意到2<=k<=5,范围非常小,且 2,3,5都是质数,很好判断,再单独判断4这个特殊情况。代码写时,注意先把所有的k都求出来,再单独求k=4,比较好求

int n,k;
const int N=2e5+10;
int a[N];

void solve()
{
    cin>>n>>k;
    for(int i = 1;i<=n;i++)cin>>a[i];
    int ans=1e8;
    for(int i = 1;i<=n;i++)
    {
        int t;
        t=(a[i]/k+1)*k-a[i];
        if(a[i]%k==0)t=0;
        ans=min(ans,t);
    }
    if(k==4)
    {
        int t;
        int ou=0;
        int ji=0;
        for(int i = 1;i<=n;i++)
        {
            if(a[i]%2==0)ou++;
            else ji++;
        }
        if(ou>=2)t=0;
        else if(ou==1)t=1;
        else t=2;
        ans=min(ans,t);
    }
    cout<<ans<<endl;
}

D. In Love

题意:将区间加入或删除,判断是否存在不相交的区间

思路:使用multiset(可重复且自动排序),存起来左和右的值,判断左最大和右最小的大小

收获:学习multiset的用法,

multiset<int> l,r;

void solve()
{
    char s;
    int a,b;
    cin>>s>>a>>b;
    if(s=='+')
    {
        l.insert(a);
        r.insert(b);
    }
    else
    {
        l.erase(l.find(a));
        r.erase(r.find(b));
    }

    if(l.size()>1 && *l.rbegin()>*r.begin())yes;
    else no;
}

E. Look Back

题意:操作为ai乘2,求多少次操作使a变为一个不减序列

思路:将每次变化数记录下来,如果后比前大的话,就是负数。ans每次加前缀和,如果前缀和为负,就变成0

收获:传统思路会爆long long 和 int,利用前缀和优化

#define int long long

int n;
const int N=2e5+10;
int a[N],b[N];

void solve()
{
    cin>>n;
    for(int i = 1;i<=n;i++) cin>>a[i];
    for(int i = 2;i<=n;i++)
    {
        int s=0;
        if(a[i]>=a[i-1])
        {
            while((a[i]>>s)>=a[i-1])s++;
            b[i]=1-s;
        }
        else
        {
            while((a[i]<<s)<a[i-1])s++;
            b[i]=s;
        }
    }
    int ans=0,sum=0;
    for(int i = 2;i<=n;i++)
    {
        sum+=b[i];
        if(sum<0)sum=0;
        ans+=sum;
    }
    cout<<ans<<endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值