习题集

CF1373D. Maximum Sum on Even Positions (最大字段和)

链接:https://codeforces.com/contest/1373/problem/D

题意:给定一个长度为 n 的数组。你可以选择一个连续区间 [ l , r ] [l,r] [l,r],将这个区间翻转,最多翻转一次。问奇数位的和最大是多少?

思路:首先翻转必然是选择偶数个数,不然对答案无影响。

  • 对答案产生影响只有两种情况,一种是偶数位和前面的奇数位,另一种是偶数位和后面的奇数产生影响。
  • 然后就变成了一个最大连续子段和的问题。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+10;

int t,n,a[maxn];

int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        ll ans1=0,ans2=0;
        for(int i=1;i<=n;i+=2) ans1+=a[i];
        for(int i=1;i<=2;++i)
        {
            vector<int> vec;
            for(int j=i+1;j<=n;j+=2)
            {
                if(i==1) vec.push_back(a[j]-a[j-1]);
                else vec.push_back(a[j-1]-a[j]);
            }
            ll sum=0,m=vec.size();
            ll res=0;
            for(int j=0;j<m;++j)
            {
                sum+=vec[j];
                res=max(res,sum);
                if(sum<0) sum=0;
            }
            ans2=max(ans2,res);
        }
        printf("%lld\n",ans1+ans2);
    }
    return 0;
}
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+10,maxm=5e5+10;

int t,n;
ll a[maxn],b[maxn];

int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        ll res=0;
        for(int i=1;i<=n;++i)
        {
            cin>>a[i];
            if(i%2==1) res+=a[i];
        }

        for(int i=1;i<=n;++i)
        {
            if(i%2==1) a[i]*=-1;
            b[i]=b[i-1]+a[i];
        }

        ll ans=0;
        for(int s=1;s<=2;++s)
        {
            ll mi=0;
            for(int i=s;i<=n;i+=2)
            {
                ans=max(ans,b[i]-mi);
                mi=min(mi,b[i]);
            }
        }
        printf("%lld\n",ans+res);
    }
    return 0;
}

CF1330C. Dreamoon Likes Coloring (思维 + 贪心)

链接:https://codeforces.com/contest/1330/problem/C

题意:给定 n n n 个格子,有 m m m 次染色操作,每次将连续 l i l_i li 个格子染成颜色 i ,要求最后每种颜色都能看到,且每个格子都被染色。请你输出每次染色的起点 p i p_i pi

思路:先将起点设在 [ 1 ,m],然后在拉伸填充空位。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,inf=1e9;

int n,m;
int l[maxn],p[maxn];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; ++i) scanf("%d",&l[i]);
    bool ok=1;
    ll sum=0;
    for(int i=1; i<=m; ++i)
    {
        p[i]=i;
        sum+=l[i];
        if(i+l[i]-1>n) ok=0;
    }
    if(!ok||sum<n)
    {
        puts("-1");
        return 0;
    }
    p[m+1]=n+1;
    for(int i=m; i>=1; --i)
    {
        if(p[i]+l[i]>=p[i+1]) break;
        p[i]=p[i+1]-l[i];
    }
    for(int i=1; i<=m; ++i)
        printf("%d%c",p[i],i==m?'\n':' ');
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值