【Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2) C. Cram Time】 贪心


C. Cram Time

题意

给你两个数a,b,用a,b分别构造两个序列A,B,
要求A序列的和小于a,B序列的和小于b
而且A序列中和B序列中每个数最多在两个序列中出现一次
要是最终的两个序列的长度和最大,输出两个序列

做法

a + b 1 + 2 + 3 + . . . + n 判断出a+b能够造的的最大的1+2+3+...+n
如果a+b>=(1+2+3+…n),一定可以构造出(1+2+3+…n)
至于构造方法,就先用a,b中大的数从大到小选,再用小的从大到小选,就OK了!

代码

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
ll a,b;
vector<int> v1,v2;
int vis[maxn];
int main()
{
    scanf("%lld%lld",&a,&b);
    ll sum=a+b;
    ll pos=0;
    for(ll i=0;;i++)
    {
        if((1LL*i*(i+1))/2==sum)
        {
            pos=i;
            break;
        }
        else if((1LL*i*(i+1))/2>sum)
        {
            pos=i-1;
            break;
        }
    }
    ll maxx=max(a,b);
    ll minn=min(a,b);
    ll tmp=sum-(1LL*pos*(pos+1))/2;
    for(int i=pos;i>=1;i--)
    {
        if(maxx>=i)
        {
            v1.push_back(i);
            maxx-=(i);
            vis[i]=1;
        }
    }
    for(int i=pos;i>=1;i--)
    {
        if(vis[i]) continue;
        if(minn>=i)
        {
            v2.push_back(i);
            vis[i]=1;
            minn-=i;
        }
    }
    if(a>=b)
    {
        printf("%d\n",v1.size());
        for(int i=0;i<v1.size();i++) printf("%d ",v1[i]);
        printf("\n%d\n",v2.size());
        for(int i=0;i<v2.size();i++) printf("%d ",v2[i]);
    }
    else
    {
        printf("%d\n",v2.size());
        for(int i=0;i<v2.size();i++) printf("%d ",v2[i]);
        printf("\n%d\n",v1.size());
        for(int i=0;i<v1.size();i++) printf("%d ",v1[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38891827/article/details/84559363