Description
QwQ非常喜欢玩部落冲突,但他从来不升级城墙,所以他的城墙开始时全都是1级的。
一天QwQ心血来潮,他先把他的
然而QwQ发现给每个城墙升到他想要的等级,不多升也不少升并不是一件容易的事,因为部落冲突只支持每次将一段城墙升高一级。
形式化地说,你的每次操作只能选择一对
由于QwQ比较懒,他需要最小化操作的次数,把墙刷到他想要的等级。(具体输出方式见输出格式)
与真实游戏不同的是,你不能调换城墙的顺序。
Input
第一行包括一个整数第二行包括
Output
第一行输出一个整数接下来
原来的城墙等级为
差分就变成了
于是对
显然总操作数就等于
为了优化过程,所以尝试构建两个差分数列
#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;
}