【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

子任务

  1. (5 分)N≤8
  2. (12 分)N≤20
  3. (32 分)N≤5000
  4. (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

子任务

  1. (5 分)N≤8
  2. (12 分)N≤20
  3. (32 分)N≤5000
  4. (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;
}

posted @ 2025-10-10 11:03  bz02_2023f2  阅读(2)  评论(0)    收藏  举报  来源