hdu 5057 Argestes and Sequence

来源:互联网 发布:凯聪智云软件下载 编辑:程序博客网 时间:2024/05/01 19:28

Argestes and Sequence

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 511    Accepted Submission(s): 127


Problem Description
Argestes has a lot of hobbies and likes solving query problems especially. One day Argestes came up with such a problem. You are given a sequence a consisting of N nonnegative integers, a[1],a[2],...,a[n].Then there are M operation on the sequence.An operation can be one of the following:
S X Y: you should set the value of a[x] to y(in other words perform an assignment a[x]=y).
Q L R D P: among [L, R], L and R are the index of the sequence, how many numbers that the Dth digit of the numbers is P.
Note: The 1st digit of a number is the least significant digit.
 

Input
In the first line there is an integer T , indicates the number of test cases.
For each case, the first line contains two numbers N and M.The second line contains N integers, separated by space: a[1],a[2],...,a[n]—initial value of array elements.
Each of the next M lines begins with a character type.
If type==S,there will be two integers more in the line: X,Y.
If type==Q,there will be four integers more in the line: L R D P.

[Technical Specification]
1<=T<= 50
1<=N, M<=100000
0<=a[i]<=$2^{31}$ - 1
1<=X<=N
0<=Y<=$2^{31}$ - 1
1<=L<=R<=N
1<=D<=10
0<=P<=9
 

Output
For each operation Q, output a line contains the answer.
 

Sample Input
15 710 11 12 13 14Q 1 5 2 1Q 1 5 1 0Q 1 5 1 1Q 1 5 3 0Q 1 5 3 1S 1 100Q 1 5 3 1
 

Sample Output
511501
 

Source
BestCoder Round #11 (Div. 2)
 

题解:

       这道题有三种版本的 题解,本来题目不难,就是限制空间:1.分块算法解决,2.离线树状数组,3.卡空间的树状数组

 

这里先介绍第一种算法:

       学习了一下分块算法,其实还蛮简单的,就是将n组元素分成m组,每组合并成一块,查询时,只要看元素在那几块,相加就行了。

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>using namespace std;struct Block{    int nt[10][10];}block[400];int num[100010];int cal(int d){    int ans=1;    for(int i=1;i<=d;i++)    {        ans*=10;    }    return ans;}int init(int n){    int s=(int)sqrt((double)n),t=0;    int m=n/s+1;    memset(block,0,sizeof(block));    for(int i=1;i<=n;i++)    {        scanf("%d",&num[i]);        s=i/m;t=num[i];        for(int j=0;j<=9;j++)        {            block[s].nt[j][t%10]++;            t/=10;        }    }    return m;}void work(int k,int n,int m){    char s[2];    int l,r,d,p,tl,tr,td,tp,ans=0;    while(m--)    {        scanf("%s",s);        if(s[0]=='S')        {            scanf("%d%d",&d,&p);            td=d;td/=k;            for(int j=0;j<=9;j++)            {                block[td].nt[j][num[d]%10]--;                num[d]/=10;            }            num[d]=p;tp=p;            for(int j=0;j<=9;j++)            {                block[td].nt[j][tp%10]++;                tp/=10;            }        }        else        {           ans=0;           scanf("%d%d%d%d",&l,&r,&d,&p);           tl=l;tl/=k;tr=r;tr/=k;d--;           td=cal(d);           if(tl==tr)           {               for(int i=l;i<=r;i++)               if(num[i]/td%10==p)               {                   ans++;               }               printf("%d\n",ans);           }           else           {               for(int i=tl+1;i<tr;i++)               {                   ans+=block[i].nt[d][p];               }               tl=(tl+1)*k;               for(int i=l;i<tl;i++)               if(num[i]/td%10==p)               {                   ans++;               }               tr*=k;               for(int i=tr;i<=r;i++)               if(num[i]/td%10==p)               {                   ans++;               }               printf("%d\n",ans);           }           //cout<<"??"<<endl;        }    }}int main(){    int cas,m,n;    scanf("%d",&cas);    while(cas--)    {        scanf("%d%d",&n,&m);        int k=init(n);        work(k,n,m);    }    return 0;}


下面还写一写离线处理的代码,随后跟上。







0 0
原创粉丝点击