bzoj1562 [NOI2009]变换序列
NOI也有SB题系列。
一个(i)只有两种可能的(T_i)
要求所有(T_i)不重复,且字典序坠小。
仔细想一想匈牙利匹配的过程就可以知道:要从后往前寻找匹配&优先匹配小的(T)。
匈牙利秒之。
// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
rg int x=0;bool flg=0;rg char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')flg=1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return flg?-x:x;
}
const int maxn=10001;
int A[maxn],B[maxn];
int match[maxn];bool vis[maxn];
il bool dfs(int x){
if(!vis[A[x]]){
vis[A[x]]=1;
if(match[A[x]]==-1||dfs(match[A[x]])){
match[A[x]]=x;
return 1;
}
}
if(!vis[B[x]]){
vis[B[x]]=1;
if(match[B[x]]==-1||dfs(match[B[x]])){
match[B[x]]=x;
return 1;
}
}
return 0;
}
int T[maxn];
int main(){
int n=gi(),d;
rep(i,0,n-1){
d=gi(),A[i]=(i+d)%n,B[i]=(i-d+n)%n;
if(A[i]>B[i])swap(A[i],B[i]);
}
memset(match,-1,sizeof match);
drep(i,n-1,0){
memset(vis,0,sizeof vis);
if(!dfs(i)){puts("No Answer");return 0;}
}
rep(i,0,n-1)T[match[i]]=i;
rep(i,0,n-1)printf("%d ",T[i]);
puts("");
return 0;
}