题目描述##:传送门
题解:
这题显然是二分图完美匹配。然后只要考虑一下字典序最小就好了。
代码如下:
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int maxn=200005;
int n,sum,tot,lnk[maxn],nxt[2*maxn],son[2*maxn],ans[maxn],ans1[maxn],a[5];
bool vis[maxn];
inline int read(){
int x=0; char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x;
}
void add(int x,int y){son[++tot]=y,nxt[tot]=lnk[x],lnk[x]=tot;}
bool dfs(int x){
for (int j=lnk[x];j!=-1;j=nxt[j])
if (!vis[son[j]]) {
vis[son[j]]=1;
if (ans[son[j]]==-1||dfs(ans[son[j]])) {ans[son[j]]=x,ans1[x]=son[j]; return 1;}
}
return 0;
}
int main(){
n=read();
memset(ans,-1,sizeof(ans));
memset(ans1,-1,sizeof(ans1));
memset(lnk,-1,sizeof(lnk));
for (int i=0;i<n;i++) {
int x=read();
a[1]=i-x,a[2]=i+x;
if (a[1]<0) a[1]+=n; if (a[2]>=n) a[2]=a[2]%n;
if (a[1]<a[2]) swap(a[1],a[2]);
add(i,a[1]); add(i,a[2]);
}
for (int i=n-1;i>=0;i--) {memset(vis,0,sizeof(vis)); if (dfs(i)) sum++; else break;}
if (sum!=n) printf("No Answer\n"); else
for (int i=0;i<n;i++) printf("%d ",ans1[i]);
return 0;
}