[CC-SEAPERM2]Sereja and Permutations
阿新 • • 發佈:2018-10-25
tmp auto clas line lag 多個 個數 cal second ,說明被刪去\(p_1\)的不可能是這個排列。)
[CC-SEAPERM2]Sereja and Permutations
題目大意:
有一個\(n(n\le300)\)排列\(p\),將其中一個元素\(p_i\)拿掉,然後將原來大於\(p_i\)的元素減一,這樣就得到一個新的排列。
將\(p\)中每一個數拿掉之後都會得到一個新的排列,這樣就得到了\(n\)個新的排列。
現在給出最後得到的\(n\)個新的排列(順序隨機),請求出原來的排列。如果有多個解,輸出字典序最小的解。保證至少有一個解。
思路:
枚舉哪一個排列被刪掉了\(p_1\),那麽剩下排列的第一個數,要麽是\(p_1\),要麽是\(p_1-1\)。(如果剩下不止兩種數,或者相差超過\(1\)
這樣,我們就可以得到\(p_1\),從而得到初始的排列,但是我們還要刪去每一個數看看是否和給你的排列一樣來驗證。做法是hash+map。
時間復雜度\(\mathcal O(n^3)\)。
源代碼:
#include<map> #include<cstdio> #include<cctype> #include<climits> #include<algorithm> inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } typedef unsigned long long uint64; const int N=301; const uint64 base=31; bool have_ans; int n,a[N][N],b[N],ans[N]; std::map<uint64,int> map; inline uint64 hash(int a[]) { uint64 ret=0; for(register int i=1;i<n;i++) { ret=ret*base+a[i]; } return ret; } inline bool check() { for(register int i=1;i<=n;i++) { if(b[i]<ans[i]) return true; if(b[i]>ans[i]) return false; } return false; } inline void upd() { if(!have_ans||check()) { have_ans=true; for(register int i=1;i<=n;i++) ans[i]=b[i]; } } int main() { for(register int T=getint();T;T--) { n=getint(); if(n==1) { puts("1"); return 0; } for(register int i=1;i<=n;i++) { for(register int j=1;j<n;j++) { a[i][j]=getint(); } } have_ans=false; for(register int i=1;i<=n;i++) { int max[2]={0,0}; bool three=false; for(register int j=1;j<=n;j++) { if(i!=j) { int tmp=a[j][1]; if(tmp==max[0]||tmp==max[1]) continue; for(register int k=0;k<2;k++) { if(tmp>max[k]) std::swap(max[k],tmp); } three|=tmp; } } if(three||(max[1]&&max[0]-max[1]!=1)) continue; for(register int val=max[0];val<=max[0]+1;val++) { for(register int i=1;i<=n;i++) map[hash(a[i])]++; b[1]=val; for(register int j=2;j<=n;j++) b[j]=a[i][j-1]+(a[i][j-1]>=b[1]); for(register int i=1;i<=n;i++) { uint64 ret=0; for(register int j=1;j<=n;j++) { if(i!=b[j]) ret=(uint64)ret*base+b[j]-(b[j]>i); } map[ret]--; } bool flag=true; for(auto &i:map) { if(i.second!=0) flag=false; } map.clear(); if(flag) upd(); } } for(register int i=1;i<=n;i++) { printf("%d%c",ans[i]," \n"[i==n]); } } return 0; }
[CC-SEAPERM2]Sereja and Permutations