Argestes and Sequence(分块2)

Argestes and Sequence(分块2) 

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]<=231231 - 1 
1<=X<=N 
0<=Y<=231231 - 1 
1<=L<=R<=N 
1<=D<=10 
0<=P<=9

Output

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

Sample Input

1
5 7
10 11 12 13 14
Q 1 5 2 1
Q 1 5 1 0
Q 1 5 1 1
Q 1 5 3 0
Q 1 5 3 1
S 1 100
Q 1 5 3 1

Sample Output

5
1
1
5
0
1

 

题意:给n个数,有两种操作,Q  l,r,ct,p 的意思是查询[l,r]上第ct位为p的数的个数。S i,x 是替换a[i] = x。

思路:分块做,用ans[400][10][10] 三位数组来存数据。ans[2][4][2] = 3  表示 -> 第2块第4位(千位)为2的数有3个。

查询操作时,不要对ans数组做更新。

判断数x的第ct位是否为p,可以写成 if (  x/qpow(10,ct-1)%10==p )

 

代码:

#include <bits/stdc++.h>

using namespace std;

const int maxn = 100005;
typedef long long ll;
int ans[400][10][10];
int a[maxn];
int belong[maxn];
int L[maxn];
int R[maxn];
int n,m;
int num;

ll qpow( ll a, ll n )
{
    ll re = 1;
    while ( n ) {
        if ( n&1 ) {
            re *= a;
        }
        n >>= 1;
        a *= a;
    }
    return re;
}

void built()
{
    int block = (int)sqrt(1.0*n);
    num = n/block;
    if ( n%block ) {
        num ++;
    }

    for ( int i=1; i<=num; i++ ) {
        L[i] = (i-1)*block+1;
        R[i] = i*block;
    }
    R[num] = n;

    for ( int i=1; i<=n; i++ ) {
        belong[i] = (i-1)/block + 1;
    }
}

void update( int i, int x )
{
    int date = a[i];
    for ( int j=1; j<=10; j++ ) {
        ans[belong[i]][j][date%10] --;
        date /= 10;
    }
    a[i] = x;

    for ( int j=1; j<=10; j++ ) {
        ans[belong[i]][j][x%10] ++;
        x /= 10;
    }
}

int query( int l, int r, int ct, int p )
{
    int re = 0,i,j;
    if ( belong[l]==belong[r] ) {
        for ( i=l; i<=r; i++ ) {
            if ( a[i]/qpow(10,ct-1)%10==p ) {
                re ++;
            }
        }
        return re;
    }

    for ( i=l; i<=R[belong[l]]; i++ ) {
        if ( a[i]/qpow(10,ct-1)%10==p ) {
            re ++;
        }
    }

    for ( i=belong[l]+1; i<belong[r]; i++ ) {
        re += ans[i][ct][p];
    }

    for ( i=L[belong[r]]; i<=r; i++ ) {
        if ( a[i]/qpow(10,ct-1)%10==p ) {
            re ++;
        }
    }
    return re;
}

int main()
{
    int listt,i,j;
    scanf("%d",&listt);
    while ( listt-- ) {
        memset(ans,0,sizeof(ans));
        scanf("%d %d",&n,&m);
        built();
        for (i=1; i<=n; i++  ) {
            scanf("%d",&a[i]);
            int x = a[i];
            for ( j=1; j<=10; j++ ) {
                ans[belong[i]][j][x%10] ++;
                x /= 10;
            }
        }

        char str[5];
        int a1,a2,a3,a4;
        while ( m-- ) {
            scanf("%s",str);
            if ( str[0]=='Q' ) {
                scanf("%d %d %d %d",&a1,&a2,&a3,&a4);
                printf("%d\n",query(a1,a2,a3,a4));
            }
            else if ( str[0]=='S' ) {
                scanf("%d %d",&a1,&a2);
                update(a1,a2);
            }
        }
    }

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值