1. 程式人生 > >JZOJ100031.【NOIP提高A組模擬】外星密碼

JZOJ100031.【NOIP提高A組模擬】外星密碼

Description在這裡插入圖片描述

SOLUTION

  • 結論題、大水題,然鵝我考場上並沒有想到結論(甚至可以說根本就沒有往那個十分顯然的規律上想),無限覺得這題不可做卻又覺得很水。。。。。。
  • 首先顯然最後一列為答案的集合
  • 顯然將其排序得到第一列前面一堆0,後面一堆1,於是最後一列與第一列的每一位置一一相連。現在有一個問題就是我們不知道哪個0對應的是哪個0。
  • 這裡有一個性質:假設最後一個位置i對應的是第一列的r[i],如果a[x]=a[y],x<y,r[x]<r[y]。也就是最前的0對應左列最前的0.
  • 證明: 兩個位置i,j,a[i]=a[j],i<j,即以i為結尾的字典序要比以j為結尾的字典序小,由於最後一位相同不考慮,那麼下一位的r[i]就應該在r[j]的前面,才能滿足條件。
  • 所以以最右列的第一個0為起點跳一跳就好了
  • 其實輸入有一種無解的情況,就是當有a[k]=1時a[1]=0,因為這樣的話對應的第一列也為0,但實際上如果將這個0移到前面答案更優,所以不會“跳不動”。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 10005
using namespace std;

int n,i,j,t,b[maxn];
struct arr{int x,y;} a[maxn];
int cmp(arr a,arr b){return a.x<b.x||a.x==b.x&&a.y<b.y;}

int main(){
	scanf("%d",&n);
	for(i=1;i<=n;i++) scanf("%d",&a[i].x),a[i].y=i,b[i]=a[i].x;
	sort(a+1,a+1+n,cmp);
	t=a[1].y;
	for(i=1;i<=n;i++) 
		printf("%d ",b[t]),t=a[t].y;
}