题目链接
题意:改变数字,使得数组成为一个递增序列。
题解:很简单,就是分析可以发现必须是a[n-1]<a[n],否则不成立,因为最后两个数无法改变。在一个就是a[n]>=0,否则只有本来就是递增序列的才会成立,其余不成立,因为这样的话改变只会变成一个更大的数。
开始的时候我没有分析出来这些,所以用了一个笨的方法,但是WA了,下面是wa的代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define int long long
const int N=2e5+10;
int a[N];
int suf[N];//记录后缀
int place[N];//记录后缀的位置
bool st[N];
signed main()
{
int t;cin>>t;while(t--){
memset(suf,0,sizeof(suf));//倒这来比较好//memset(place,0,sizeof(place));memset(st,false,sizeof(st));int n;cin>>n;for(int i=1;i<=n;i++) cin>>a[i];int flag1=1;if(is_sorted(a+1,a+1+n)){
printf("0\n");continue;}if(a[n-1]>a[n]){
printf("-1\n");continue;}int minn=0x3f3f3f3f3f3f3f3f;int mini=0;for(int i=n;i>=1;i--){
if(a[i]>=0&&a[i]<minn) minn=a[i],mini=i;suf[i]=minn;//找到最小整数place[i]=mini;//最小整数的位置}int ans=0;for(int i=n-2;i>=1;i--){
if(suf[i+2]==0x3f3f3f3f3f3f3f3f) continue;else a[i]=a[i+1]-suf[i+2];}int flag=1;for(int i=2;i<=n;i++){
if(a[i]<a[i-1]){
flag=0;break;}}if(flag==0){
printf("-1\n");continue;}else{
printf("%lld\n",n-2);for(int i=n-2;i>=1;i--){
printf("%lld %lld %lld\n",i,i+1,place[i+2]);}}}return 0;
}
这里错误的主要原因是place那,记录的位置没有错误,错在了其实本题虽然是按照静态来处理,但实则是一个动态的问题,那么数改变之后可能就不在原来的位置了,所以这里发生了错误。
这里还要注意的是所有数都相等也是一种递增序列,所以要注意是a[i]>=0。
下面是简洁的AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define int long long
const int N=2e5+10;
int a[N];
bool st[N];
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--){
int n;cin>>n;for(int i=1;i<=n;i++) cin>>a[i];if(a[n]>=0&&a[n]>=a[n-1]){
printf("%lld\n",n-2);for(int i=n-2;i>=1;i--){
printf("%lld %lld %lld\n",i,i+1,n);}}else{
if(is_sorted(a+1,a+1+n)) printf("0\n");else printf("-1\n");}}return 0;
}