Description
Alice又想到一个游戏:N个数每个数都在0到9之间,可以对每一个数进行加1操作,但这个加1比较特别,0-8加1后会相应变成1-9,但9加1后会变成0,给出N个数,进行M次操作,每次操作都会给出两个整数A和B(1<=A<=B<=N),要求输出第A个数到第B个数的和,然后把A到B之间的每一个数进行一次加1操作。
你能帮助Alice吗?
Input
输入文件第一行包含两个整数N和M(1<=N<=250000,1<=M<=100000);
第二行N个数字,每个数字都在0到9之间,中间没有空格,表示初始值。
接下来M行,每行包含两个整数A和B(1<=A<=B<=N)
Output
输出M行,每行表示对应区间的和,注意是先计算后操作。
Sample Input
输入1:
4 3
1234
1 4
1 4
1 4
输入2:
4 4
1234
1 1
1 2
1 3
1 4
输入3:
7 5
9081337
1 3
3 7
1 3
3 7
1 3
Sample Output
输出1:
10
14
18
输出2:
1
4
9
16
输出3:
17
23
1
19
5
Data Constraint
Hint
【数据范围】
30%的数据N,M<=1000
这题的正解是线段树,不过比普通线段树难搞很多
这里的线段树每一个点维护一个0~9的序列,表示0~9出现了多少次
每次修改时就把0~8改到1~9的次数,9改成0的次数,然后再下传标记
由于转x次相当于转x%10次,所以这里相当于一个小优化
打起来比较麻烦,而且还有一个大坑——
pascal卡常!思路完全对!答案是对的!超了几百+ms!woc……mdzz……RNMMP……
于是怒改c++强行开O3切掉,只不过code极其难看……
type
point=record
sum,flag,p:longint;
a:array[0..9]of longint;
end;
var
tree:array[0..1234567]of point;
n,m,i,j,x,y:longint;
ch:char;
procedure update(x:longint);
var
i,k:longint;
begin
tree[x].p:=tree[x].p mod 10;
for i:=1 to tree[x].p do
begin
k:=tree[x].a[9];
for j:=9 downto 1 do
tree[x].a[j]:=tree[x].a[j-1];
tree[x].a[0]:=k;
end;
tree[x].sum:=0;
for i:=0 to 9 do
inc(tree[x].sum,tree[x].a[i]*i);
tree[x].p:=0;
end;
procedure downdata(x:longint);
var
i,j,k:longint;
begin
inc(tree[2*x].flag,tree[x].flag);
inc(tree[2*x+1].flag,tree[x].flag);
inc(tree[2*x+1].p,tree[x].flag);
inc(tree[2*x].p,tree[x].flag);
tree[x].flag:=0;
update(x*2);
update(x*2+1);
update(x);
tree[x].flag:=0;
end;
procedure maketree(x,l,r:longint);
var
i,mid:longint;
begin
if l=r then
begin
read(ch);
tree[x].a[ord(ch)-48]:=1;
tree[x].sum:=ord(ch)-48;
exit;
end;
mid:=(l+r)shr 1;
maketree(2*x,l,mid);
maketree(2*x+1,mid+1,r);
tree[x].sum:=tree[2*x].sum+tree[2*x+1].sum;
for i:=0 to 9 do
tree[x].a[i]:=tree[2*x].a[i]+tree[2*x+1].a[i];
end;
function solve(x,y,t,l,r:longint):longint;
var
mid:longint;
begin
downdata(t);
if (l>=x)and(r<=y)then
begin
exit(tree[t].sum);
end;
mid:=(l+r)shr 1;
if mid>=y then exit(solve(x,y,2*t,l,mid))
else if midthen exit(solve(x,y,2*t+1,mid+1,r))
else exit(solve(x,y,2*t,l,mid)+solve(x,y,2*t+1,mid+1,r));
end;
procedure change(t,l,r,x,y:longint);
var
i,j,k,mid:longint;
begin
downdata(t);
if (l>=x)and(r<=y)then
begin
inc(tree[t].flag);
inc(tree[t].p);
downdata(t);
exit;
end;
mid:=(l+r)shr 1;
if y<=mid then change(2*t,l,mid,x,y)
else if x>mid then change(2*t+1,mid+1,r,x,y)
else
begin
change(2*t,l,mid,x,y);
change(2*t+1,mid+1,r,x,y);
end;
tree[t].sum:=tree[t*2].sum+tree[t*2+1].sum;
for i:=0 to 9 do
tree[t].a[i]:=tree[2*t].a[i]+tree[2*t+1].a[i];
end;
begin
readln(n,m);
maketree(1,1,n);
for i:=1 to m do
begin
readln(x,y);
writeln(solve(x,y,1,1,n));
change(1,1,n,x,y);
end;
end.
#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include
using namespace std;
int f[1020251],a[264451],s[1020251],p[1020251],val[1020251][10];
int n,m,t,l,r,c,nn;
char str[264451];
void tsum(int v)
{
f[v]=f[v*2]+f[v*2+1];
for(int i=0;i<=9;i++)
{
val[v][i]=val[v*2][i]+val[v*2+1][i];
}
}
void maketree(int v,int l,int r)
{
if(l==r)
{
f[v]=a[l];
val[v][a[l]]++;
return;
}
int mid=(l+r)>>1;
maketree(v*2,l,mid);
maketree(v*2+1,mid+1,r);
tsum(v);
}
void update(int x)
{
if(x>=nn)return;
int o[10];
for(int i=0;i<10;i++)o[(i+p[x])%10]=val[x][i];
memcpy(val[x],o,sizeof(o));
f[x]=0;
for(int i=0;i<10;i++)
f[x]+=val[x][i]*i;
p[x]=0;
}
void doit(int v)
{
s[v*2]+=s[v],s[v*2+1]+=s[v],p[v*2]+=s[v],p[v*2+1]+=s[v],s[v]=0;
update(v*2);
update(v*2+1);
update(v);
}
void change(int v,int l,int r,int x,int y)
{
if(l==x && r==y)
{
s[v]++;
p[v]++;
update(v);
return;
}
doit(v);
int mid=(l+r)/2;
if(y<=mid)change(v*2,l,mid,x,y);
if(x>mid)change(v*2+1,mid+1,r,x,y);
if(!(y<=mid||x>mid)){
change(v*2,l,mid,x,mid);
change(v*2+1,mid+1,r,mid+1,y);
}
tsum(v);
}
int find(int v,int l,int r,int x,int y)
{
if(l==x&&r==y)
{
return f[v];
}
doit(v);
int mid=(l+r)/2;
if(x>mid)return find(v*2+1,mid+1,r,x,y);
if(y<=mid)return find(v*2,l,mid,x,y);
return find(v*2,l,mid,x,mid)+find(v*2+1,mid+1,r,mid+1,y);
}
int main()
{
scanf("%d%d%s",&n,&m,str+1);
for(int i=1;i<=n;i++)a[i]=int(str[i])-48;
t=n,nn=1;
for(;t>1;t=(t+1)/2,nn*=2);
nn*=2;
maketree(1,1,n);
while(m--)
{
scanf("%d%d",&l,&r);
printf("%d\n",find(1,1,n,l,r));
change(1,1,n,l,r);
}
}