JZOJsenior1384. Alice的游戏

来源:互联网 发布:mac系统 流程图 编辑:程序博客网 时间:2024/05/19 11:46

题目描述

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极其难看……


pascal code(70分)

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 mid<x then 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.

c++ code(AC)

#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#include<bits/stdc++.h>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);    }}
阅读全文
0 0
原创粉丝点击