题目
Problem Description
wzj同学熟悉电脑操作,于是他找了一个打字员的工作。他的工作主要是编辑一个有n行的文本,每一行的字符数量不尽相同。如我们所知的一样,文本中有一个光标,它一开始在第1行的最后一个字符后面,wzj可以在光标的位置输入或删除字符。当然,他也可以用方向键移动光标,可以往上、下、左、右移动。要注意的是,如果当前光标所在的位置前面有a个字符,如果要将其向下(上)移动,而下(上)一行的字符不足a个,那么光标就会落在下(上)一行的最后一个字符后面。
现在,wzj知道这个文本的行数n和每一行所含的字符数ai,他的上司给了他一个操作序列,共有q个操作,操作分为3种,如下:
To a:将光标移到第a行的最后一个字符之后。
Insert a:在当前光标所在行的末端插入a个字符。
Delete a:在当前光标所在行的末端删除a个字符。
已知向上、下、左、右移动一格,插入或删除一个字符都需要1次按键,而wzj又是一个很懒的人,他想知道要完成这些操作至少需要多少次按键。特殊地,如果删除操作中当前行的字符不足a个,则按键数应为该行有的字符数。
Input
第一行有2个以空格间隔的整数n和q,意义如题目描述中所述。
接下来的一行,有n个以空格间隔的整数,其中第i个整数表示第i行的字符数ai。
接下来的q行,每一行有一个操作指令,格式如题目描述中所述。
1≤n,q≤200000,操作过程中每行的字符数不超过1000000,输入的指令均合法,行首没有空格。
Output
输出一个整数,为完成操作至少所需的按键次数(结果可能较大,建议使用long long型存储)。
Sample Input
5 5
2 3 2 4 2
To 2
Insert 2
To 4
Delete 5
To 2Sample Output
19
样例说明(移动指令中上下左右以UDLR代替)
第1个操作,以“DR”顺序移动,按键数为2。
第2个操作,按键数为2,第2行字符数变为5。
第3个操作,以“DDRR”顺序移动,按键数为4。
第4个操作,第4行字符数不足5个,所以只需4次按键,第4行字符数变为0。
第5个操作,以“URRURRR”顺序移动,按键数为7。
所以按键数总共为2+2+4+4+7=19次。
分析
- 我们发现,每次操作后光标都在当前行最后面,而从第 i 行移到第 j 行,只按上下到那一行后,光标的位置是区间
[i,j]
字符数的最小值,之后再向右移到最后面就行了。 - 鉴于数据范围,就用线段树维护一下每行字符数的区间最小值。
程序
#include <cstdio>
#include <algorithm>
#include <cstring>
#define Mid ((l+r)>>1)
#define L (x<<1)
#define R (L+1)
using namespace std;
int t[800005],a[200005],aim,Min,Max,nx,ny,n,q,k;
char ch[20];
long long ans;
void bui(int x,int l,int r){
if (l==r){a[l]=(scanf("%d",&t[x]),t[x]); return;}
bui(L,l,Mid);
bui(R,Mid+1,r);
t[x]=min(t[L],t[R]);
}
int que(int x,int l,int r){
if (l>=Min && r<=Max) return t[x];
int xx=2147483647,yy=2147483647;
if (Mid>=Min) xx=que(L,l,Mid);
if (Mid+1<=Max) yy=que(R,Mid+1,r);
return min(xx,yy);
}
void chg(int x,int l,int r){
if (l==r){t[x]+=aim; return;}
if (Mid>=nx) chg(L,l,Mid);
if (Mid+1<=nx) chg(R,Mid+1,r);
t[x]=min(t[L],t[R]);
}
int main(){
memset(t,0x7f,sizeof(t));
scanf("%d%d",&n,&q);
bui(1,1,n);
nx=1,ny=a[1];
while (q--){
scanf("%s %d",ch,&aim);
if (ch[0]=='T'){
ans+=abs(aim-nx);
Min=min(nx,aim);
Max=max(nx,aim);
k=que(1,1,n); ans+=abs(a[aim]-k);
nx=aim,ny=a[aim];
}
if (ch[0]=='I'){
chg(1,1,n);
a[nx]=ny+=aim;
ans+=aim;
}
if (ch[0]=='D'){
aim=-min(ny,aim);
chg(1,1,n);
a[nx]=ny+=aim;
ans-=aim;
}
}
printf("%lld",ans);
}