CF549G题解
变菜了,一年前做这种题10min出结论,现在对着样例胡半天都没结果
首先考虑从判断无解入手。
定义两个位置 \((i,j)\),若 \(a[i]=a[j]+(j-i)\),则 \(i\) 和 \(j\) 贴贴。别问我为啥叫贴贴,因为这个真的很形象
让我们考虑执行若干次操作,足够多操作结束后,这两个元素 仍然贴贴,并且相邻。证明很简单。
然后你发现,每进行一次操作,这玩意儿不变,但是仍然可以继续进行操作。
也就是如果存在两个贴贴的元素,那么无解。
然后考虑解决问题。假如 \(a[i]\) 最终需要移动到 \(j\),那么最终的序列 \(b\) 上,\(b[j]=a[i]+i-j\)。证明也很简单。
所以问题变成了将 \(a[i]+i\) 分配位置,使最终的序列单调不降。排序就好了。
而且排好序后还方便判断无解。
#include<algorithm>
#include<cstdio>
typedef unsigned uint;
uint a[200005];
signed main(){
register uint i,n;scanf("%u",&n);
for(i=1;i<=n;++i)scanf("%u",a+i),a[i]+=i;std::sort(a+1,a+n+1);
for(i=1;i^n;++i)if(a[i]==a[i+1])return!printf(":(");
for(i=1;i<=n;++i)printf("%u ",a[i]-i);
}