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;
}