题目
思路
不难发现,一个人往左移动 1 1 1 ,手上的钱便增加 1 1 1 。所以,设其原来在第 i i i 位,现在在第 j j j 位,那他就会获得 i − j i-j i−j 元。甚至更形象一点:一个人的金钱数与下标之和不变。
如果发现了这一点,肯定就应该直接排序了,因为站在最后的人一定是失去了最多的钱。或者说, s i − i ≤ s j − j s_i-i\le s_j-j si−i≤sj−j 而 i < j i<j i<j 故 s i < s j s_i<s_j si<sj 。排序后检查即可。
代码
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
inline int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0'||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
template < typename T >
void getMax(T&a,const T&b){if(a<b)a=b;}
template < typename T >
void getMin(T&a,const T&b){if(b<a)a=b;}
const int MaxN = 200005;
struct Node{
int sum, val;
bool operator < (const Node &that) const {
return sum < that.sum;
}
} node[MaxN];
int a[MaxN];
int main(){
int n = readint();
for(int i=1; i<=n; ++i){
node[i].val = readint();
node[i].sum = node[i].val+i;
}
sort(node+1,node+n+1);
for(int i=1; i<=n; ++i){
a[i] = node[i].sum-i;
if(a[i-1] > a[i] || a[i] < 0){
puts(":("); return 0;
}
}
for(int i=1; i<n; ++i)
printf("%d ",a[i]);
printf("%d\n",a[n]);
return 0;
}
后记
A t C o d e r \rm AtCoder AtCoder 为您精心准备了双倍经验,戳 S w a p s 2 \rm Swaps\; 2 Swaps2 即刻领取吧!