题意:原有一数组A,用B在记录A的最长不递增序列,现在告诉你pi对应的b[pi]值,要求还原出一组可行的C数组,使得1-pi位置的最长不递增序列长度为b[pi]
ps:好像我的解法和主流解法不同,而且还稍微慢一些,跑了600+ms
个人解析:
将1-n放入一个单调递增队列q里,暂时假设所有位置都是无穷大,将pi从大到小排序。
不存在的情况:i<k时,存在b[pi]-b[p(i-1)]>pi-p(i-1)时则答案不存在,因为pi-p(i-1)最多只能放下pi-p(i-1)个元素
①当pi-b[pi]+1到pi都没有重新填入数字时,我们将q的前b[pi]个元素一次填入pi-b[pi]+1到pi处,可以保证1-pi的最长不递增序列长度为b[pi]:pi-b[pi]+1之前的数都是无穷大,所以全部都被弹出,同时可以保证已经处理过的不会受到影响:更小的数字先填入,所以已经填入的数字都小于pi-b[pi]+1到pi的数字,所以后方的数字会把现在填的全部弹出
②当pi-b[pi]+1到pi都填入时,由于确保了b[pi]-b[p(i-1)]>pi-p(i-1),所以我们可以不用更改就满足条件,这条不理解可以自己琢磨一下,给出例子: b[2]=1,b[5]=4,b[6]=5
③当pi-b[pi]+1到pi部分填入时,由于pi从大到小处理,可知被填入的是后半部分,此时我们将被这段中重新填入过的元素回收到q里面,我们再将q的前b[pi]个元素一次填入pi-b[pi]+1到pi处,此时显然可以满足1-pi的最长不递增序列长度为b[pi],也可以保证已处理的不会受到影响:有①②可知被填入的数字是来自同一个p的处理,由于先填入的数字是较小的,我们将回收的数字再填入显然不会影响到已处理的结果,然后填入的非回收数字是大于所有已填的数字的,会被已填的数字给弹出,所以也不会影响已处理过的结果
AcCode
#include<iostream>
#include<algorithm>
#include<set>
#include<cstdio>
#include<queue>
using namespace std;
//#define int long long
//#define inf 1010000000
const int N = 1e6 + 100;
set<int> st;
int out[N];
priority_queue<int, vector<int>, greater<int> >q;
struct node {
int index;
int len;
node() {};
node(int index, int len) :index(index), len(len) {};
}arr[N];
inline bool cmp(node a, node b) {
return a.index > b.index;
}
signed main() {
int n, k;
//cin >> n >> k;
scanf("%d %d", &n, &k);
bool ret = false;
for (int i = 1; i <= n; i++) q.push(i);
for (int i = 1; i <= k; i++) {
int p, x;
scanf("%d %d", &p, &x);
if (x > p) ret = true;
arr[i] = node(p, x);
}
if (ret) {
printf("-1\n");
return 0;
}
sort(arr + 1, arr + 1 + k, cmp);
for (int i = 1; i < k; i++) {
if ((arr[i].index - arr[i + 1].index) < (arr[i].len - arr[i + 1].len)) {
printf("-1\n");
return 0;
}
}
for (int i = 1; i <= k; i++) {
if (out[arr[i].index - arr[i].len + 1]) continue;
for (int j = arr[i].index - arr[i].len + 1; j <= arr[i].index; j++) {
if (out[j]) q.push(out[j]);
}
for (int j = arr[i].index - arr[i].len + 1; j <= arr[i].index; j++) {
out[j] = q.top();
q.pop();
}
}
int maxm = n;
for (int i = 1; i <= n; i++) {
if (!out[i]) {
out[i] = maxm--;
}
}
for (int i = 1; i <= n; i++) printf("%d ", out[i]);
printf("\n");
}