Description

QwQ非常喜欢玩部落冲突,但他从来不升级城墙,所以他的城墙开始时全都是1级的。

一天QwQ心血来潮,他先把他的个城墙排成一排,然后在脑中构思好每个城墙要被升到几级。

然而QwQ发现给每个城墙升到他想要的等级,不多升也不少升并不是一件容易的事,因为部落冲突只支持每次将一段城墙升高一级。

形式化地说,你的每次操作只能选择一对满足,然后将第到第块城墙各升高一级。

由于QwQ比较懒,他需要最小化操作的次数,把墙刷到他想要的等级。(具体输出方式见输出格式)

与真实游戏不同的是,你不能调换城墙的顺序。

Input

第一行包括一个整数表示QwQ的城墙个数。

第二行包括个整数表示第块城墙QwQ想要刷到的级别。

Output

第一行输出一个整数,表示你的操作次数,如果有多种操作次数最小的操作方式,你可以输出任何一个。(保证操作次数的最小值在以内)

接下来行,每行2个整数表示你给第到第个城墙每块升了一级。


原来的城墙等级为

差分就变成了

于是对进行差分并将第一项减一,接下来要操作的就是对数列各项归零。

显然总操作数就等于数列所有正项之和。

为了优化过程,所以尝试构建两个差分数列分别代表中的正项和负项并舍弃0项。(为了操作便利,对数列取绝对值)


#define f(i, a, b) for (int i = a; i <= b; i++)
#define scan(x) scanf("%d", &x)
    int left[100086], right[100086], leftc[100086], rightc[100086],res=0,cntl=2,cntr=1,last,now,x,fz=1;
    /*leftc和rightc分别代表L和R数列,right和left数组分别记录leftc和rightc各项指向的墙块序号/
    scan(last);/*last记录上一输入值*/
    left[1] = 1;
    leftc[1] = last - 1;
    res += last - 1;
    f(i, 2, x)
    {
        scan(now);
        if (now > last)
        {
            res += now - last;
            left[cntl] = i;
            leftc[cntl++] = now - last;
        }
        if(now<last){
            right[cntr] = i;
            rightc[cntr++] = last - now;
        }
        last = now;
    }

这样的话,就可以在输入后直接开始输出了

先输出一个左界,然后输出右界,如果右界在数组没有,就输出边界值

而上面差分出来的就代表指向的墙块序号要输出的次数了

#define pn(x) printf("%d", x)
    pn(res);
    f(i,1,cntl-1){
        while(leftc[i]--)
            {
                printf("\n%d ", left[i]);
                if(rightc[fz]>0){
                    printf("%d", right[fz]-1);
                    rightc[fz] -= 1;
                    if(rightc[fz]==0)
                        fz += 1;
                }
                else
                    printf("%d", x);
            }
    }

于是:

#include <stdio.h>
#include <stdlib.h>

#define max(x, y) x < y ? y : x
#define min(x, y) x < y ? x : y
#define LL long long
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "w", stdout)
#define scan(x) scanf("%d", &x)
#define sqr(x) (x) * (x)
#define f(i, a, b) for (int i = a; i <= b; i++)
#define pn(x) printf("%d", x)
#define pr1(x) printf("Case %d: ", x)
#define pn1(x) printf("Case %d:\n", x)
#define pr2(x) printf("Case #%d: ", x)
#define pn2(x) printf("Case #%d:\n", x)
#define lowbit(x) (x & (-x))
int left[100086], right[100086], leftc[100086], rightc[100086],res=0,cntl=2,cntr=1,last,now,x,fz=1;

int main()
{
    //IN;
    //OUT;
    scan(x);
    scan(last);
    left[1] = 1;
    leftc[1] = last - 1;
    res += last - 1;
    f(i, 2, x)
    {
        scan(now);
        if (now > last)
        {
            res += now - last;
            left[cntl] = i;
            leftc[cntl++] = now - last;
        }
        if(now<last){
            right[cntr] = i;
            rightc[cntr++] = last - now;
        }
        last = now;
    }
    pn(res);
    f(i,1,cntl-1){
        while(leftc[i]--)
            {
                printf("\n%d ", left[i]);
                if(rightc[fz]>0){
                    printf("%d", right[fz]-1);
                    rightc[fz] -= 1;
                    if(rightc[fz]==0)
                        fz += 1;
                }
                else
                    printf("%d", x);
            }
    }
    return 0;
}
此文章已被阅读次数:正在加载...更新于