Argestes and Sequence
Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 566 Accepted Submission(s): 142
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
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个基本单位)东西分成sqrt(n)块, 每块包含sqrt(n)个基本单位。
如果要修改某个基本单位,只要修改该单位所在的块,因为每块包含sqrt(n)个基本单位,所以时间复杂度为sqrt(n);
view code#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const int N = 100010; struct Block { int ct[10][10]; }block[400]; int _, n, m, a[N], cnt, pp[11]; void build() { int tmp = (int)sqrt(n*1.0), id; cnt = n/tmp + 1; memset(block, 0, sizeof(block)); for(int i=0; i<n; i++) { scanf("%d", &a[i]); id = i/cnt, tmp = a[i]; for(int j=0; j<10; j++) { block[id].ct[j][tmp%10]++; tmp /= 10; } } } void update(int u, int v) { int id = u/cnt; for(int i=0; i<10; i++) { block[id].ct[i][a[u]%10]--; a[u] /= 10; } a[u] = v; for(int i=0; i<10; i++) { block[id].ct[i][v%10]++; v /= 10; } } int query(int l, int r, int d, int p) { int L = l/cnt, R = r/cnt; int res = 0, div = pp[d]; if(L==R) { for(int i=l; i<=r; i++) if(a[i]/div%10==p) res++; return res; } for(int i=L+1; i<R; i++) { res += block[i].ct[d][p]; } for(int i=l; i<(L+1)*cnt; i++) { if(a[i]/div%10==p) res++; } for(int i=R*cnt; i<=r; i++) { if(a[i]/div%10==p) res++; } return res; } void solve() { scanf("%d%d", &n, &m); build(); char str[5]; int u, v, d, p; while(m--) { scanf("%s", str); if(str[0]=='S') { scanf("%d%d", &u, &v); u--; update(u, v); } else { scanf("%d%d%d%d", &u, &v, &d, &p); u--, v--, d--; printf("%d\n", query(u, v, d, p)); } } } void init() { pp[0] = 1; for(int i=1; i<10; i++) pp[i] = pp[i-1]*10; } int main() { // freopen("in.txt", "r", stdin); init(); cin>>_; while(_--) solve(); return 0; }