Codeforces Round #713 (Div. 3)-E. Permutation by Sum-题解

231 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

@TOC

Codeforces Round #713 (Div. 3)-E. Permutation by Sum

传送门 Time Limit: 2 seconds Memory Limit: 256 megabytes

Problem Description

A permutation is a sequence of nn integers from 11 to nn, in which all the numbers occur exactly once. For example, [1][1], [3,5,2,1,4][3, 5, 2, 1, 4], [1,3,2][1, 3, 2] are permutations, and [2,3,2][2, 3, 2], [4,3,1][4, 3, 1], [0][0] are not.

Polycarp was given four integers nn, ll, rr (1lrn)1 \le l \le r \le n) and ss (1sn(n+1)21 \le s \le \frac{n (n+1)}{2}) and asked to find a permutation pp of numbers from 11 to nn that satisfies the following condition:

For example, for n=5n=5, l=3l=3, r=5r=5, and s=8s=8, the following permutations are suitable (not all options are listed):

Help Polycarp, for the given nn, ll, rr, and ss, find a permutation of numbers from 11 to nn that fits the condition above. If there are several suitable permutations, print any of them.

Input

The first line contains a single integer tt (1t5001 \le t \le 500). Then tt test cases follow.

Each test case consist of one line with four integers nn (1n5001 \le n \le 500), ll (1ln1 \le l \le n), rr (lrnl \le r \le n), ss (1sn(n+1)21 \le s \le \frac{n (n+1)}{2}).

It is guaranteed that the sum of nn for all input data sets does not exceed 500500.

Output

For each test case, output on a separate line:

If there are several suitable permutations, print any of them.

Sample Input

5
5 2 3 5
5 3 4 1
3 1 2 4
2 2 2 2
2 1 1 3

Sample Onput

1 2 3 4 5 
-1
1 3 2 
1 2 
-1

题目大意

给你44个数nlrsn、l、r、s,让你找到一个nn的全排列,它满足从第ll个数累加到第rr个数的和等于ss


解题思路

nn的全排列中,最大的数是nn,最小的数是11,且各个数各不相同。 所以llrrrl+1r-l+1个数(记为numnum)中,和的最小值是m=1+2++num=(1+num)num/2m=1+2+\cdots+num=(1+num)*num/2,和的最大值是M=(nnum+1)+(nnum+2)++n=(nnum+1+n)num/2M=(n-num+1)+(n-num+2)+\cdots+n=(n-num+1+n)*num/2。 如果ss界于这两个数之间,就能找到符合条件的全排列,否则就不行。 如果可以找到,就把llrr中的数先初始值为最小的11numnum,再不断将这些数变大(变得尽量大),知道他们的和等于ss。 变大过程是从最后一个数(numnum)开始变到尽可能大(不超过nn且和不超过ss),然后倒数第二个数(num1num-1)开始变到尽可能大(不超过n1n-1且和不超过ss\cdots知道和等于ss


AC代码

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int a[505];
int getNext(map<int,bool>::iterator &it)//找到下一个输出的数(可以先看下面主函数)
{
    while(it->second==false)it++;//这个数出现过了,继续往下找
    return it->first;//找到返回
}
int main()
{
    int N;
    cin>>N;
    while(N--)//N组测试样例
    {
        int n,l,r,s;
        cin>>n>>l>>r>>s;
        int num=r-l+1;//从l到r共有r-l+1个数
        int m=(1+num)*num/2;//和最小为m
        int M=(n-num+1+n)*num/2;//和最大为M
        if(s<m||s>M)//如果s不介于他们之间
        {
            puts("-1");//不行
            continue;
        }
        for(int i=0;i<num;i++)//l到r初始值从1到num
        {
            a[i]=i+1;
        }
        int diff=s-m;//s比现在的这num个数大diff,还需要再加上diff
        int toM=n;//一个数最大变到n
        int loc=num-1;//目前处理的数的下标(从第r个数开始处理)
        while(diff)//差值不为0
        {
            int thisMaxDiff=toM-a[loc];//这个数改变所能引起的最大的差值
            int thisRealDiff=min(thisMaxDiff, diff);//真正变大的量(不能超过diff)
            diff-=thisRealDiff;//差距减小了thisRealDiff
            a[loc]+=thisRealDiff;//这个数变大了thisRealDiff
            toM=a[loc]-1;//一个数最大变到的数-1
            loc--;//下次处理前面一个数
        }
        map<int,bool>ma;//map储存一个数是否还能使用
        for(int i=1;i<=n;i++)
        {
            ma[i]=1;//初始值还可以使用
        }
        for(int i=0;i<num;i++)
        {
            ma[a[i]]=0;//从l到r中要出现的数不能再使用
        }
        map<int,bool>::iterator it=ma.begin();//从头开始找
        // for(map<int,bool>::iterator temp=ma.begin();temp!=ma.end();temp++)
        // {
        //     printf("%d %d\n",temp->first, temp->second);
        // }
        loc=0;
        for(int i=1;i<=n;i++)
        {
            if(i>=l&&i<=r)//是l到r中的一个数
            {
                printf("%d ",a[loc++]);//以及计算出,直接输出
            }
            else//否则
            {
                printf("%d ",getNext(it));//没出现过的数中找到下一个
                it++;
            }
        }
        puts("");//换行
    }
    return 0;
}

同步发文于我的CSDN,原创不易,转载请附上原文链接哦~
Tisfy:letmefly.blog.csdn.net/article/det…