Codeforces 1244G Running in Pairs 序列交换(贪心)

链接:https://codeforces.com/contest/1244/problem/G

题意:给出2个序列p,q长度为n,元素都是1,2 ,3....n,给出k,求 尽可能大 sigma(max(pi, qi))且小于k的时候如何安排序列的元素,若无法满足条件,-1

题解:贪心,最小的情况两个序列都是1,2,3,4...n,最大的情况一个序列顺序一个序列倒序,求和和k比较可判断是否有解,

   要求尽可能大的,我们不断的a[i]和a[n-i+1]进行交换,这样交换产生的贡献是递减的并且连续的,若在x处交换后超过了k,我们一定可以右边向走左找到最优解。

#include <bits/stdc++.h>
#define IO_read ios::sync_with_stdio(false);cin.tie(0)
#define fre freopen("in.txt", "r", stdin)
#define _for(i,a,b) for(int i=a; i< b; i++)
#define _rep(i,a,b) for(int i=a; i<=b; i++)
#define inf 0x3f3f3f3f
#define lowbit(a) ((a)&-(a))
using namespace std;
typedef long long ll;
template <class T>
void read(T &x)
{
    char c; bool op=0;
    while(c=getchar(), c<'0'||c>'9') if(c=='-') op=1;
    x=c-'0';
    while(c=getchar(), c>='0'&&c<='9') x=x*10+c-'0';
    if(op) x=-x;
}
template <class T>
void write(T x)
{
    if(x<0) putchar('-'), x=-x;
    if(x>=10) write(x/10);
    putchar('0'+x%10);
}

const int maxn=1e6+5;
int a[maxn], b[maxn];
ll n, k, ans, max_ans;

int main()
{
    IO_read;
    //fre;
    cin>>n>>k;
    if(k<n*(n+1)/2){
        cout<<-1<<"
"; return 0;
    }
    max_ans= n&1? ((n+1)/2+n)*(n+1)/2-(n+1)/2:(n+(n+2)/2)*n/2;
    if(k>=max_ans){
        cout<<max_ans<<"
";
        for(int i=1; i<=n; i++) cout<<i<<" 
"[i==n];
        for(int i=n; i>=1; i--) cout<<i<<" 
"[i==1];
        return 0;
    }
    ans=n*(n+1)/2;
    for(int i=1; i<=n; i++) a[i]=b[i]=i;
    for(int i=1; i<=n/2; i++)
    {
        int val=a[n-i+1]-a[i];
        if(ans+val>k){
            int j=i+k-ans;
            ans=ans+a[j]-a[i];
            swap(a[i], a[j]);
            break;
        }
        ans+=val; swap(a[i], a[n-i+1]);
    }
    cout<<ans<<"
";
    for(int i=1; i<=n; i++) cout<<a[i]<<" 
"[i==n];
    for(int i=1; i<=n; i++) cout<<b[i]<<" 
"[i==n];
    return 0;
}
原文地址:https://www.cnblogs.com/Yokel062/p/11760928.html