Non-decreasing(AtCoder-3720)

Problem Description

Snuke has an integer sequence, a, of length N. The i-th element of a (1-indexed) is ai.

He can perform the following operation any number of times:

Operation: Choose integers x and y between 1 and N (inclusive), and add ax to ay.
He would like to perform this operation between 0 and 2N times (inclusive) so that a satisfies the condition below. Show one such sequence of operations. It can be proved that such a sequence of operations always exists under the constraints in this problem.

Condition: a1≤a2≤…≤aN

Constraints

  • 2≤N≤50
  • −106≤ai≤106
  • All input values are integers.

Input

Input is given from Standard Input in the following format:

N
a1 a2 … aN

Output

Let m be the number of operations in your solution. In the first line, print m. In the i-th of the subsequent m lines, print the numbers x and y chosen in the i-th operation, with a space in between. The output will be considered correct if m is between 0 and 2N (inclusive) and a satisfies the condition after the m operations.

Example

Sample Input 1

3
-2 5 -1

Sample Output 1

2
2 3
3 3
After the first operation, a=(−2,5,4).
After the second operation, a=(−2,5,8), and the condition is now satisfied.

Sample Input 2

2
-1 -3

Sample Output 2

1
2 1
After the first operation, a=(−4,−3) and the condition is now satisfied.

Sample Input 3

5
0 0 0 0 0

Sample Output 3

0
The condition is satisfied already in the beginning.

题意:给出一个长度为 n 的序列,每次可以将序列中的一个数 a[x] 加到序列中的另一个数 a[y] 上,要求在 2n 次操作内使得序列满足 a[1]<=a[2]<=...<=a[n],输出要操作的次数 m 以及每次操作的两个数的序号 x、y

思路:

首先扫一遍判断初始序列是否非递减,若是非递减,则直接输出 0 即可

若不是非递减,则找到序列中绝对值最大的值,并将所有数都加上这个绝对值,此时分两种情况:

  • 若绝对值最大的数为正数:对所有数都加上这个绝对值后,可保证所有数都是正数,此时从前向后扫一遍,令后者加上前者即可
  • 若绝对值最大的数为负数:对所有数都加上这个绝对值后,可保证所有数都是负数,此时从后向前扫一遍,令后者加上前者

由于要求操作次数在 m=2n 以内,通过以上的两步扫描,无论何种情况,仅需 2*n-1 次操作,即可构造出一个非递减序列

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 50+5;
const int dx[] = {-1,1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;

int a[N];
int main(){
    int n;
    scanf("%d",&n);

    int maxx=-INF;
    int pos=-1;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if(abs(a[i])>maxx){
            pos=i;
            maxx=abs(a[i]);
        }
    }

    bool flag=true;
    for(int i=1;i<=n-1;i++)
        if(a[i]>=a[i+1])
            flag=false;

    if(flag)
        printf("0\n");
    else{
        printf("%d\n",2*n-1);
        for(int i=1;i<=n;i++)
            printf("%d %d\n",pos,i);

        if(a[pos]>0)
            for(int i=1;i<=n-1;i++)
                printf("%d %d\n",i,i+1);
        else
            for(int i=n;i>=2;i--)
                printf("%d %d\n",i,i-1);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值