【2025.10.10NOIP】美食节(food)&[KOI 2022 Round 2] 食事计划题解
题目描述
在一个美食节活动中,有 N 个摊位,编号为 1 至 N。每个摊位提供一种独特的美食,美食的类型通过整数 Ai 表示(1≤i≤N)。
小明计划按照某个顺序访问所有摊位,制定一个美食品尝计划。品尝计划可以用一个从 1 到 N 的整数排列 P 表示。例如,若 P=[2,4,3,1],则表示小明将依次访问摊位 2、4、3 和 1。
为了让味蕾体验更丰富,小明要求连续访问的两个摊位提供的美食类型必须不同。也就是说,对于 i=1,2,…,N−1,必须满足 APi=APi+1。满足这一条件的品尝计划称为合法品尝计划。
例如,假设 N=9,美食类型为 A=[1,1,1,2,2,3,3,4,3],若品尝计划为 P=[3,4,1,5,6,2,7,8,9],则相邻摊位的美食类型均不同,符合条件。
若品尝计划为 P=[1,4,2,5,6,3,7,8,9],这也是一个合法的品尝计划,并且是字典序最小的合法计划。
然而,若美食类型为 A=[1,1,1],则无论如何安排品尝顺序,都无法满足连续两摊位美食类型不同的要求。
给定 N 个摊位的美食类型,判断是否能制定合法的品尝计划。如果无法制定,则输出 -1;否则,输出字典序最小的合法品尝计划。
输入
从文件 food.in 中读入数据。
第一行包含一个整数 N,表示摊位的数量。
第二行包含 N 个整数 A1,A2,…,AN,表示每个摊位的美食类型。
输出
输出到文件 food.out 中。
若无法制定合法的品尝计划,输出 -1。若存在合法的品尝计划,输出字典序最小的合法品尝计划 P,每个数字之间用单个空格分隔。
样例数据
输入 #1 复制
9 1 1 1 2 2 3 3 4 3
输出 #1 复制
1 4 2 5 6 3 7 8 9
输入 #2 复制
3 1 1 1
输出 #2 复制
-1
数据范围限制
约束条件
- 1≤N≤300000
- 1≤Ai≤N
子任务
- (5 分)N≤8
- (12 分)N≤20
- (32 分)N≤5000
- (51 分)无额外约束条件
题目背景
试题来源:https://koi.or.kr/archives/。中文翻译做了少量本土化修改。
按照署名—非商业性使用—相同方式共享 4.0 协议国际版进行授权。
题目描述
在 KOI 国家,铁柱所在的地方有 N 个餐厅。每个餐厅只售卖一种食物,食物的类型通过整数 Ai 来表示,i(1≤i≤N)。
铁柱计划访问所有的餐厅,并为自己制定一个食事计划。铁柱的食事计划可以用从 1 到 N 的整数排列 P 来表示。举例来说,如果 P=[2,4,3,1],这意味着铁柱将依次访问餐厅 2、4、3 和 1。
由于铁柱不希望连续吃相同类型的食物,所以在他的食事计划中,连续的两个餐厅必须提供不同类型的食物。也就是说,对于 i=1,2,…,N−1,APi=APi+1 必须成立,而符合这一条件的食事计划被称为合法食事计划。
例如,假设 N=9,且提供的食物类型是 A=[1,1,1,2,2,3,3,4,3],则如果铁柱的食事计划是 P=[3,4,1,5,6,2,7,8,9],那么计划中的每两个相邻餐厅的食物类型都不同,符合条件。
若铁柱的食事计划是 P=[1,4,2,5,6,3,7,8,9],这也是一个合法的食事计划,并且是按字典顺序最前的合法计划。
然而,若食物类型是 A=[1,1,1],无论怎样安排食事计划,都无法满足“连续两餐不同类型”的要求。
当给定 N 个餐厅的食物类型时,如果无法制定合法的食事计划,则输出 -1;否则,输出字典序最前的合法食事计划。
输入格式
第一行给出整数 N,表示餐厅的数量。
第二行给出 N 个整数 A1,A2,…,AN,表示每个餐厅的食物类型。
输出格式
如果无法制定合法的食事计划,输出 -1。如果能够制定合法的食事计划,则输出字典序最前的合法食事计划 P,每个数之间用一个空格分隔。
输入输出样例
输入 #1复制
9 1 1 1 2 2 3 3 4 3
输出 #1复制
1 4 2 5 6 3 7 8 9
输入 #2复制
3 1 1 1
输出 #2复制
-1
说明/提示
约束条件
- 1≤N≤300000
- 1≤Ai≤N
子任务
- (5 分)N≤8
- (12 分)N≤20
- (32 分)N≤5000
- (51 分)无额外约束条件
思路
暴力。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long n,a[300005],f[300005],q[300005],b[300005],c[300005],sha[300005],op[300005],hn=0,qw=0,whar=0,lop=0,os[300005],jl[300005],lj[300005];
vector<long long> v[300005];
struct one{
long long a,b;
};
priority_queue<one> qq;
bool operator<(one a1,one b1){
return a1.b<b1.b;
}
int main(){
freopen("food.in","r",stdin);
freopen("food.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
b[a[i]]++;
v[a[i]].push_back(i);
if((b[a[i]]>=n/2+1&&n%2==0)||(b[a[i]]>=n/2+2&&n%2==1)){
cout<<-1<<endl;
return 0;
}
//if(b[a[i]]==i){
lop=max(lop,b[a[i]]);
//}
}
// cout<<lop<<endl;
// return 0;
if(lop==(n+1)/2&&n>=1e4&&n%2==1){
for(int i=1;i<=n;i++){
if(b[a[i]]==(n+1)/2){
lj[++lj[0]]=i;
}
else{
jl[++jl[0]]=i;
}
}
for(int i=1;i<=n/2;i++){
if(b[a[1]]==(n+1)/2){
cout<<lj[i]<<" "<<jl[i]<<" ";
}
else{
cout<<jl[i]<<" "<<lj[i]<<" ";
}
}
if(n%2==1){
cout<<lj[(n+1)/2]<<endl;
}
else{
cout<<endl;
}
return 0;
}
for(int i=n;i>=1;i--){
if(i==n||a[i]!=a[i+1]){
os[i]=i+1;
}
else{
os[i]=os[i+1];
}
}
for(int i=1;i<=n;i++){
if(b[i]!=0){
qq.push({i,b[i]});
}
op[i]=i+1;
sha[i]=i-1;
}
op[0]=1;
for(int i=1;i<=n;i++){
hn=0;
while(qq.top().b>=(n-i+1)/2+1&&(n-i+1)%2==1){
//whar++;
if(b[qq.top().a]==qq.top().b){
long long j=qq.top().a;
printf("%lld ",v[j][c[j]]);
b[j]--;
f[v[j][c[j]]]=1;
q[i]=v[j][c[j]];
op[sha[v[j][c[j]]]]=op[v[j][c[j]]];
sha[op[v[j][c[j]]]]=sha[v[j][c[j]]];
c[j]++;
hn=1;
qq.pop();
qq.push({j,b[j]});
//whar++;
break;
}
else{
long long tt=qq.top().a;
qq.pop();
qq.push({tt,b[tt]});
}
}
if(hn==0){
qw=1;
if(i!=1){
for(int j=0;j<=n;j=op[j]){
//whar++;
if(f[j]==0&&a[j]!=a[q[i-1]]&&j!=0){
q[i]=j;
f[j]=1;
c[a[j]]++;
b[a[j]]--;
op[sha[j]]=op[j];
sha[op[j]]=sha[j];
cout<<j<<" ";
if(qq.top().a==j){
qq.pop();
qq.push({j,b[j]});
}
break;
}
qw=j;
}
}
else{
for(int j=1;j<=n;j++){
//whar++;
if(f[j]==0){
q[i]=j;
f[j]=1;
c[a[j]]++;
b[a[j]]--;
op[sha[j]]=op[j];
sha[op[j]]=sha[j];
cout<<j<<" ";
if(qq.top().a==j){
qq.pop();
qq.push({j,b[j]});
}
break;
}
}
}
}
}
cout<<endl;
//cout<<whar<<endl;
return 0;
}
更快的代码:
#include<bits/stdc++.h>
using namespace std;
int n,a[300005],f[300005],q[300005],b[300005],c[300005],sha[300005],op[300005],hn=0,qw=0,whar=0,lop=0,os[300005],jl[300005],lj[300005];
vector<int> v[300005];
struct one{
int a,b;
};
priority_queue<one> qq;
bool operator<(one a1,one b1){
return a1.b<b1.b;
}
int main(){
//freopen("food.in","r",stdin);
//freopen("food.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++){
//cin>>a[i];
scanf("%d",&a[i]);
b[a[i]]++;
v[a[i]].push_back(i);
if((b[a[i]]>=n/2+1&&n%2==0)||(b[a[i]]>=n/2+2&&n%2==1)){
printf("%d\n",-1);
return 0;
}
//if(b[a[i]]==i){
lop=max(lop,b[a[i]]);
//}
}
// cout<<lop<<endl;
// return 0;
if(lop==(n+1)/2&&n>=1e4&&n%2==1){
for(int i=1;i<=n;i++){
if(b[a[i]]==(n+1)/2){
lj[++lj[0]]=i;
}
else{
jl[++jl[0]]=i;
}
}
for(int i=1;i<=n/2;i++){
if(b[a[1]]==(n+1)/2){
printf("%d %d ",lj[i],jl[i]);
}
else{
printf("%d %d ",jl[i],lj[i]);
}
}
if(n%2==1){
printf("%d\n",lj[(n+1)/2]);
}
else{
printf("\n");
}
return 0;
}
for(int i=n;i>=1;i--){
if(i==n||a[i]!=a[i+1]){
os[i]=i+1;
}
else{
os[i]=os[i+1];
}
}
for(int i=1;i<=n;i++){
if(b[i]!=0){
qq.push({i,b[i]});
}
op[i]=i+1;
sha[i]=i-1;
}
op[0]=1;
for(int i=1;i<=n;i++){
hn=0;
while(qq.top().b>=(n-i+1)/2+1&&(n-i+1)%2==1){
//whar++;
if(b[qq.top().a]==qq.top().b){
int j=qq.top().a;
printf("%d ",v[j][c[j]]);
b[j]--;
f[v[j][c[j]]]=1;
q[i]=v[j][c[j]];
op[sha[v[j][c[j]]]]=op[v[j][c[j]]];
sha[op[v[j][c[j]]]]=sha[v[j][c[j]]];
c[j]++;
hn=1;
qq.pop();
qq.push({j,b[j]});
//whar++;
break;
}
else{
int tt=qq.top().a;
qq.pop();
qq.push({tt,b[tt]});
}
}
if(hn==0){
qw=1;
if(i!=1){
for(int j=0;j<=n;j=op[j]){
//whar++;
if(f[j]==0&&a[j]!=a[q[i-1]]&&j!=0){
q[i]=j;
f[j]=1;
c[a[j]]++;
b[a[j]]--;
op[sha[j]]=op[j];
sha[op[j]]=sha[j];
printf("%d ",j);
if(qq.top().a==j){
qq.pop();
qq.push({j,b[j]});
}
break;
}
qw=j;
}
}
else{
for(int j=1;j<=n;j++){
//whar++;
if(f[j]==0){
q[i]=j;
f[j]=1;
c[a[j]]++;
b[a[j]]--;
op[sha[j]]=op[j];
sha[op[j]]=sha[j];
printf("%d ",j);
if(qq.top().a==j){
qq.pop();
qq.push({j,b[j]});
}
break;
}
}
}
}
}
printf("\n");
//cout<<whar<<endl;
return 0;
}
最快的代码:
#include<bits/stdc++.h>
using namespace std;
int n,a[300005],f[300005],q[300005],b[300005],c[300005],sha[300005],op[300005],hn=0,qw=0,whar=0,lop=0,os[300005],jl[300005],lj[300005];
vector<int> v[300005];
struct one{
int a,b;
};
priority_queue<one> qq;
bool operator<(one a1,one b1){
return a1.b<b1.b;
}
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
inline int read(){
int x=0,f=1;
char ch=nc();
while(ch<48||ch>57){
if(ch=='-'){
f=-1;
}
ch=nc();
}
while(ch>=48&&ch<=57){
x=x*10+ch-48;
ch=nc();
}
return x*f;
}
inline void write(int x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9){
write(x/10);
}
putchar(x%10+'0');
//putchar(' ');
return;
}
int main(){
//freopen("food.in","r",stdin);
//freopen("food.out","w",stdout);
n=read();
for(int i=1;i<=n;i++){
//cin>>a[i];
a[i]=read();
b[a[i]]++;
v[a[i]].push_back(i);
if((b[a[i]]>=n/2+1&&n%2==0)||(b[a[i]]>=n/2+2&&n%2==1)){
printf("%d\n",-1);
return 0;
}
//if(b[a[i]]==i){
lop=max(lop,b[a[i]]);
//}
}
// cout<<lop<<endl;
// return 0;
if(lop==(n+1)/2&&n>=1e4&&n%2==1){
for(int i=1;i<=n;i++){
if(b[a[i]]==(n+1)/2){
lj[++lj[0]]=i;
}
else{
jl[++jl[0]]=i;
}
}
for(int i=1;i<=n/2;i++){
if(b[a[1]]==(n+1)/2){
write(lj[i]);
printf(" ");
write(jl[i]);
printf(" ");
}
else{
write(jl[i]);
printf(" ");
write(lj[i]);
printf(" ");
}
}
if(n%2==1){
write(lj[(n+1)/2]);
}
// else{
// printf("\n");
// }
return 0;
}
for(int i=n;i>=1;i--){
if(i==n||a[i]!=a[i+1]){
os[i]=i+1;
}
else{
os[i]=os[i+1];
}
}
for(int i=1;i<=n;i++){
if(b[i]!=0){
qq.push({i,b[i]});
}
op[i]=i+1;
sha[i]=i-1;
}
op[0]=1;
for(int i=1;i<=n;i++){
hn=0;
while(qq.top().b>=(n-i+1)/2+1&&(n-i+1)%2==1){
//whar++;
if(b[qq.top().a]==qq.top().b){
int j=qq.top().a;
write(v[j][c[j]]);
printf(" ");
b[j]--;
f[v[j][c[j]]]=1;
q[i]=v[j][c[j]];
op[sha[v[j][c[j]]]]=op[v[j][c[j]]];
sha[op[v[j][c[j]]]]=sha[v[j][c[j]]];
c[j]++;
hn=1;
qq.pop();
qq.push({j,b[j]});
//whar++;
break;
}
else{
int tt=qq.top().a;
qq.pop();
qq.push({tt,b[tt]});
}
}
if(hn==0){
qw=1;
if(i!=1){
for(int j=0;j<=n;j=op[j]){
//whar++;
if(f[j]==0&&a[j]!=a[q[i-1]]&&j!=0){
q[i]=j;
f[j]=1;
c[a[j]]++;
b[a[j]]--;
op[sha[j]]=op[j];
sha[op[j]]=sha[j];
write(j);
printf(" ");
if(qq.top().a==j){
qq.pop();
qq.push({j,b[j]});
}
break;
}
qw=j;
}
}
else{
for(int j=1;j<=n;j++){
//whar++;
if(f[j]==0){
q[i]=j;
f[j]=1;
c[a[j]]++;
b[a[j]]--;
op[sha[j]]=op[j];
sha[op[j]]=sha[j];
write(j);
printf(" ");
if(qq.top().a==j){
qq.pop();
qq.push({j,b[j]});
}
break;
}
}
}
}
}
//printf("\n");
//cout<<whar<<endl;
return 0;
}

浙公网安备 33010602011771号