Codeforces Round #808 (Div. 2) C,D Codeforces Round #809 (Div. 2) C

C Doremy’s IQ
题意:n场比赛需要vp,每场比赛难度不同,vp者有一定的智商q,如果vp到了难度大于q的比赛,智商-1,现在我们希望vp尽可能多的比赛。

输出一个长度为n的01串,第i位是1代表这场比赛vp,否则代表skip

思路:首先想到的就是,如何能在智商-1后不影响后面的比赛vp,如果产生影响,后面的比赛至少会少vp一场,所以我们干脆禁止产生影响,这样我们就统计在这个位置要vp完后面所有的比赛一共需要多少智商。如果在正序遍历的过程中,发现目前位置的智商能满足后面所有的vp,那么直接全1就行了。

#include <iostream>
#define endl '\n'
using namespace std;
const int N = 1e5+100;
int a[N];
int b[N];
int main()
{
    int t;
    for(cin>>t;t;t--)
    {
        int n,q;
        cin>>n>>q;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        b[n]=1;
        for(int i=n-1;i>=1;i--)
        {
            if(a[i]<=b[i+1])
                b[i]=b[i+1];
            else
                b[i]=b[i+1]+1;
        }
        for(int i=1;i<=n;i++)
        {
            if(q>=a[i])
            {
                cout<<1;
            }
            else
            {
                if(q>=b[i])
                {
                    cout<<1;
                    q--;
                }
                else
                {
                    cout<<0;
                }
            }
        }
        cout<<endl;
    }
    return 0;
}

D. Difference Array
题意:给定一个长度为n的数组a,每次求出差分数组b(n-1项)后sort一下,然后替换原数组a,问最终剩下的数字是几

思路:题目给出一条非常重要的信息是:在t组测试样例中,所有a的和加起来不超过5e5。
这就给了非常强烈的提示了。
再想一想,只要a[i]和a[i-1]这俩不是x和0,必然会使得操作之后的总和至少减一,而有n个数就代表会至少缩减n-1。
0和0做差得到的dis必然是0,x和0得到也只能是x,最后剩下的就是一堆0和一个非0数x,或者是只剩下了一堆0
也就是说,这个题只要能达到最终至少有n-1个0就完活了。数组的总和是5e5,而每次操作又能最少让总和减少n-1(这里的n指目前的数列元素个数),所以复杂度不用担心。直接暴力

#include <iostream>
#include <algorithm>
#define int long long
#define endl '\n'
#define fastio    cout.tie(0);cin.tie(0);ios::sync_with_stdio(0);
using namespace std;
const int N = 1e5+100;
int n,t;
int a[N];
signed main()
{
    fastio
    for(cin>>t;t;t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        int st=1;
        int con=1;
        while(a[n-1])
        {
            con++;
            int dis;
            for(int i=st+1;i<=n;i++)
            {
                dis=a[i]-a[i-1];
                a[i-1]=dis;
            }
            a[n]=0;
            sort(a+st,a+n+1);
            for(int i=st;i<=n-1;i++)
            {
                if(a[i]!=0)
                {
                    st=i-1; break;
                }
            }
             st=max(con,st);
        }
        cout<<a[n]<<endl;
    }
    return 0;
}

C. Qpwoeirut And The City

题意:给定n个数,在这些数的中间部分(除去第1和第n项)构造波峰,可以选择数组里任意的数加x,这会产生x点花费,要求在构造最多波峰的前提下花费最少。求最少花费

思路:首先波峰最多很简单。奇数个数时,我们只能让第二个数作为波峰,第三个作为波谷,第四波峰,,,以此类推
偶数时,我们画图发现,波谷的长度未必是1了,可能是两个数来当波谷。但是我们发现由第2个数当波谷,和由第2个数当波峰是两个互补的情况,也就是说我们可以用这两种情况来拼凑出一个最优情况。

这样就可以愉快地前缀和+枚举贪心来做了

#include <iostream>

#define int long long
using namespace std;
const int N=1e5+100;

int a[N],b[N],c[N];
signed main()
{
    int t;
    for(cin>>t;t;t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        if(n&1)
        {
            int ans=0;
            for(int i=2;i<=n-1;i+=2)
            {
                if(a[i]<=a[i-1]||a[i]<=a[i+1])
                ans+=1+max(a[i-1],a[i+1])-a[i];
            }
            cout<<ans<<endl;
        }
        else
        {
            int ans;
            for(int i=3;i<=n-1;i+=2)
            {
                if(a[i]<=a[i-1]||a[i]<=a[i+1])
                c[i]=1+max(a[i-1],a[i+1])-a[i];
            }
            for(int i=2;i<=n-1;i+=2)
            {
                if(a[i]<=a[i-1]||a[i]<=a[i+1])
                b[i]=1+max(a[i-1],a[i+1])-a[i];
            }
            for(int i=1;i<=n;i++)
            {
                c[i]+=c[i-1];
                b[i]+=b[i-1];
            }
            ans=min(c[n-1],b[n-1]);
            for(int i=2;i<=n-1;i++)
            {
                ans=min(ans,b[i]+c[n-1]-c[i+1]);
            }
            cout<<ans<<endl;
        }
        for(int i=1;i<=n;i++)
        {
            a[i]=b[i]=c[i]=0;
        }

    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值