1512E
题意:找到给定区间长度并且区间和为s的序列;
题解:序列可能有多种情况,可以采用较为连续的序列来表示,这样
可以保证序列的每个值不会大于n;
步骤:
假如一个数字s,和区间长度len,用连续数字表示的话,
每个数字之间就会相差1,
首先把这个相差的1除去,然后就可以算出他们len个相同的初始的值,
其中这个相差的值为int k=len*(len+1)/2-len,
或者可以写成len*(len-1)/2,表示长度为len-1的公差为1的数列的和,
s-=k;s/=len;,s就是初始值,每次加一即可;
这里有可能出现s%len!=0的情况,先找到初始值,然后从后面开始依次给
每个数字+1,注意不能一次性加到某一个数字上,有可能会导致数组冲突或者
超过n,从后往前避免了数组冲突,依次+1防止超过n;
code
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
int main() {int t;cin >> t;while (t--) {int n, l, r, s;cin >> n >> l >> r >> s;ll a = (1 + r - l + 1) * (r - l + 1) / 2;//区间最小值;ll b = (n + n - r + l) * (r - l + 1) / 2;//区间最大值;if (s > b || s < a) {cout << "-1" << endl;} else {int len = r - l + 1;int p = len * (len + 1) / 2 - len;int k = (s - p) / len;vector<int> v;map<int, int> mp;if ((s - p) % len == 0) {while (len--) {v.push_back(k);mp[k]++;k++;}} else if ((s - p) % len) {int len1 = len;while (len--) {v.push_back(k);k++;}int tem = (s - p) % len1;for (int i = v.size() - 1; i >= 0; i--) {if (tem) {v[i]++;tem--;}mp[v[i]]++;}}map<int, int>mmp;for (int i = 1, cnt = 1; i <= n, cnt < l; i++) {if (mp[i] == 0) {cout << i << " ";mmp[i]++, cnt++;}}for (auto i : v) cout << i << " ";for (int i = 1; i <= n; i++) {if (mp[i] == 0 and mmp[i] == 0)cout << i << " ";}cout << endl;}}return 0;
}