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);
}
posted @ 2022-01-11 13:55  Prean  阅读(21)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};