题意:给N个数,有两种操作,S x y 将a[x]变为y;Q x y d p 寻找[x,y]之内第d位的数为p的个数。
思路:开始一想,裸的线段树呀,敲了之后,MLE,然后一愣,有点傻眼了,卡空间。然而正解是分块,就是把N分成
N − − √
份,再处理,写跪了N发之后才A。也是爽。各种WA,TLE。复杂度N*
N − − √
。
http://acm.hdu.edu.cn/showproblem.php?pid=5057
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define rep(i,a,b) for(int i = a ; i <= b ; i ++)
#define rrep(i,a,b) for(int i = b ; i >= a ; i --)
#define repE(p,u) for(Edge * p = G[u].first ; p ; p = p -> next)
#define cls(a,x) memset(a,x,sizeof(a))
#define lson rt<<1
#define rson rt<<1|1
using namespace std ;
const int MOD = 1e9 +7 ;
const int INF = 0x3f3f3f3f ;
const int MAXN = 1e5 +5 ;
const int MAXE = 2e5 +5 ;
typedef long long LL;
int T,n,m,k;
int A[400 ][11 ][10 ];
int NUM[MAXN];
int st,lt;
int tmp;
void START() {
st = sqrt (n);
lt = st * st == n ? st : st + 1 ;
int base = 0 ;
cls(A,0 );
rep(i,1 ,lt) {
rep(j,1 ,st) {
if (base+j > n) return ;
tmp = NUM[base + j];
rep(ia,1 ,10 ) {
A[i][ia][tmp%10 ] ++;
tmp /= 10 ;
}
}
base += st;
}
}
void out() {
rep(i,1 ,n) printf ("%d " ,NUM[i]);
puts ("\n" );
printf ("st : %d lt : %d\n\n" ,st,lt);
rep(i,1 ,lt) {
rep(ia,1 ,10 ) {
rep(ib,0 ,9 ) {
printf ("%d " ,A[i][ia][ib]);
}
puts ("" );
}
puts ("" );
}
puts ("\n" );
}
void Update(int pos,int num) {
int oldnum = NUM[pos];
NUM[pos] = num;
int nowpos = (pos + (st - 1 )) / st;
tmp = oldnum;
rep(ia,1 ,10 ) {
A[nowpos][ia][tmp%10 ] --;
tmp /= 10 ;
}
tmp = num;
rep(ia,1 ,10 ) {
A[nowpos][ia][tmp%10 ] ++;
tmp /= 10 ;
}
}
int ANS ;
int digit[11 ];
void Query(int left,int right,int d,int p) {
int L = (left + st - 1 ) / st + 1 ; int R = (right + st - 1 ) / st - 1 ;
if (L > R) {
rep(i,left,right) {
if ((NUM[i]/digit[d])%10 ==p)ANS ++;
}
}
else {
rep(i,L,R) {
ANS += A[i][d][p];
}
rep(i,left,(L-1 )*st) {
if ((NUM[i]/digit[d])%10 ==p)ANS ++;
}
rep(i,R*st+1 ,right) {
if ((NUM[i]/digit[d])%10 ==p)ANS ++;
}
}
}
int ReadInt() {
char tempc; int minus = 1 ; int ret = 0 ; scanf ("%c" ,&tempc);
while (tempc < '0' || tempc > '9' ) { if (tempc == '-' ) minus = -1 ; scanf ("%c" ,&tempc); }
while (tempc >= '0' && tempc <= '9' ) { ret = ret * 10 + tempc - '0' ; scanf ("%c" ,&tempc); }
return ret * minus;
}
void input() {
scanf ("%d %d" ,&n,&m);
char op[5 ];
rep(i,1 ,n) scanf ("%d" ,&NUM[i]);
digit[1 ] = 1 ;
rep(i,2 ,10 ) digit[i] = digit[i-1 ] * 10 ;
START();
int x,y,d,p;
rep(i,1 ,m) {
scanf ("%s" ,op);
if (op[0 ] == 'S' ) {
scanf ("%d %d" ,&x,&y);
Update(x,y);
}
else {
scanf ("%d %d %d %d" ,&x,&y,&d,&p);
ANS = 0 ;
Query(x,y,d,p);
printf ("%d\n" ,ANS);
}
}
}
void solve() {
}
int main(void ) {
scanf ("%d" ,&T);
while (T--) {
input();
solve();
}
return 0 ;
}