题目链接;http://acm.hdu.edu.cn/showproblem.php?pid=5057
题目大意:N个数,M 次操作(1<=N, M<=100000)。操作分两种情况,一种是将arr[x]更新成y,另一种是询问区间[L,R]中第D位上是P的数有多少个。数字987654321第i位是i。
思路:分块处理。将n分为sqrt(n)块。每块单独处理。每次查询将边界块暴力依次查询,中间块用预处理的结果直接查询。这样复杂度达到了 O(Q*(n/b+b))。
每次更新操作是将原数据的贡献减去,然后将新的贡献加上去。。刚好卡过…………联系一下分块法,平方分割法。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 100050
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define ULL unsigned long long
#define FOR(i , n) for(int i = 1 ; i<= n ; i ++)
typedef pair<int , int> pii;
const long long INF= 0x3fffffff;
int n , m;
double dis ;
int a[maxn];
struct node
{
int num[12][10];
}p[10000];
void get(int pos , int val , int flag)
{
int tmp = val , j = 1;
int index = (int)(1.0*pos/dis);
while(tmp)
{
if(flag) p[index].num[j++][tmp%10]++;
else p[index].num[j++][tmp%10]--;
tmp = tmp /10;
}
while(j <= 11)
{
if(flag) p[index].num[j++][0]++;
else p[index].num[j++][0]--;
}
}
void update(int x , int num )
{
get(x , a[x] , 0);
a[x] = num;
get(x , a[x] , 1);
}
int query(int l , int r , int pos , int index)
{
int st = (l / dis);
int ed = (r / dis);
int ans = 0;
for(int i = st + 1 ; i < ed ; i ++)
ans += p[i].num[pos][index];
for(int i = l ; i <= r ; i ++)
{
if((int)(i/dis) > st) break;
int tmp = a[i] , j = pos-1;
while(j--) tmp /= 10;
if(tmp % 10 == index) ans ++;
}
for(int i = r ; i >= l ; i --)
{
if((int)(i/dis) < ed || (int)(i/dis) == st) break;
int tmp = a[i] , j = pos-1;
while(j--) tmp /= 10;
if(tmp % 10 == index) ans ++;
}
return ans;
}
int main()
{
int t;
scanf("%d" , &t);
while(t--)
{
mem(p , 0);
scanf("%d %d" , &n , &m);
dis = sqrt(n);
for(int i = 1 ; i <= n ; i ++)
{
scanf("%d" , &a[i]);
get(i , a[i] , 1);
}
char op[2] ;
int l , r , d , p , x ,y;
for(int i = 1 ; i <= m ; i ++)
{
scanf("%s" , op);
if(op[0] == 'Q')
{
scanf("%d %d %d %d" , &l , &r , &d , &p);
printf("%d\n" , query(l , r , d , p) );
}
else if(op[0] == 'S')
{
scanf("%d %d" , &x , &y);
update(x , y);
}
}
}
return 0;
}