[agc008d]kth-k
题意:
给你一个长度为N的整数序列X,构造一个整数序列a满足:
1.a的长度为$N^2$,且1~N中每个数字恰好出现N次;
2.数字i在a中第i次出现的位置为$X_i$;
如果不能构造输出“No”,否则先输出“Yes”然后在第二行输出构造的序列(本题有SPJ)。
$1\leq N\leq 500$
$1\leq X_i\leq N^2$且$X_i$互不相同
题解:
我太菜了只会$O(n^3)$。。。dalao们纷纷$O(n^2)$碾了过去不知道比我快到哪里去了。。。
分别向前向后扫一遍,记录当前每个数字还需要填多少个,贪心填然后判断即可。
代码:
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<queue>
7 #define inf 2147483647
8 #define eps 1e-9
9 using namespace std;
10 typedef long long ll;
11 int n,N,cnt=0,s[501],num[501],tot[501],a[250001];
12 int main(){
13 scanf("%d",&n);
14 for(int i=1;i<=n;i++){
15 scanf("%d",&num[i]);
16 a[num[i]]=i;
17 tot[i]=i-1;
18 }
19 N=n*n;
20 for(int i=1;i<=N;i++){
21 if(a[i])s[++cnt]=a[i];
22 }
23 for(int i=1;i<=N;i++){
24 if(a[i])continue;
25 for(int j=1;j<=n;j++){
26 if(!tot[s[j]])continue;
27 a[i]=s[j];
28 tot[s[j]]--;
29 break;
30 }
31 }
32 for(int i=1;i<=n;i++){
33 tot[i]=n-i;
34 }
35 for(int i=N;i;i--){
36 if(a[i])continue;
37 for(int j=n;j;j--){
38 if(!tot[s[j]])continue;
39 a[i]=s[j];
40 tot[s[j]]--;
41 break;
42 }
43 }
44 for(int i=1;i<=n;i++){
45 int tmp=0;
46 for(int j=1;j<=N;j++){
47 if(a[j]==i)tmp++;
48 if(tmp==i){
49 if(j!=num[i])return puts("No"),0;
50 break;
51 }
52 }
53 }
54 puts("Yes");
55 for(int i=1;i<=N;i++)printf("%d ",a[i]);
56 return 0;
57 }
我会说我考试时去atc的submission看了一下全是熟悉的id吗