这个题主要在于需要将前后的0合并起来,因为0-0=0,所以没有必要做多余的计算
而题解给出的证明也是非常精妙
设原序列的最大值减最小值为V
设i递增序列的Max-Min==U
则可以得到如下性质:
1、第i+1个序列的最大值不会超过U
2、第i+1个序列的总和为U
因为a[i+1][1]+a[i+1][2]+....+a[i+1][n]=a[i][2]-a[i][1]+a[i][3]-a[i][2]+.....a[i][n+1]-a[i][n]
=a[i][n+1]-a[i][1]=U、
3、第i+1个序列全部大于等于0(因为序列i递增)
4、第i+1个序列的序列最多有一个数大于U/2
因此可以得到,最多会进行logV次序列操作(因为当Max-Min==0时就可以退出了)
而每次操作的复杂度为O(n),因此总的复杂度为O(n*logV)
其他的就是简单的模拟了
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int SIZEN=100005;
LL a[SIZEN];
LL t_a[SIZEN];
int val_h,val_t;
int check(int cnt){
int flag=1;
for(int i=0;i<cnt-1;i++)
if(a[i]>a[i+1]) flag=0;
if(flag) return 1;
flag=1;
for(int i=0;i<cnt-1;i++)
if(a[i]<a[i+1]) flag=0;
if(flag) return -1;
else return 0;
}
void solve(){
int n,cnt;
scanf("%d",&n);
cnt=n;
val_h=val_t=0;
for(int i=0;i<n;i++)
scanf("%I64d",&a[i]);
for(int i=0;i<=n-1;i++){
if(i==n-1||cnt==1){
printf("nice series\n");
return;
}
int flag=check(cnt);
if(flag==0){
if(i==0) printf("ugly series\n");
else printf("%d\n",i-1);
return;
}
else if(flag==-1){
for(int i=0;i<cnt/2;i++)
swap(a[i],a[cnt-1-i]);
swap(val_h,val_t);
}
int ncnt=0;
if(val_h) {t_a[ncnt++]=0;val_h--;}
for(int i=0;i+1<cnt;i++)
t_a[ncnt++]=a[i+1]-a[i];
if(val_t) {t_a[ncnt++]=0;val_t--;}
int j=1;
cnt=0;
a[cnt++]=t_a[0];
if(a[0]==0) while(t_a[j]==0&&j<ncnt) {val_h++;j++;}
for(;j<ncnt;j++) a[cnt++]=t_a[j];
if(a[cnt-1]==0) while(a[cnt-2]==0&&cnt-2>=0) {cnt--;val_t++;}
//for(int j=0;j<cnt;j++) printf("%I64d ",a[j]);printf("\n");
}
}
int main()
{
//freopen("data.in","r",stdin);
int _;
scanf("%d",&_);
while(_--) solve();
return 0;
}