HDU5057(分块)

  Argestes and Sequence

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1279    Accepted Submission(s): 373


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]<=231 - 1
1<=X<=N
0<=Y<=231 - 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
 
分块大法,降低暴力的时间复杂度
  1 //2016.8.13 
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 
  6 using namespace std;
  7 
  8 const int N = 100005;
  9 int a[N], len = 400, n, mi[15] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
 10 
 11 struct node
 12 {
 13     int cnt[12][12];//cnt[d][p]表示每个块内第d位是p的个数
 14 }block[400];
 15 
 16 bool judge(int x, int d, int p)//判断x的第d位是否为p
 17 {
 18     return x/mi[d]%10==p;
 19 }
 20 
 21 int query(int l, int r, int d, int p)
 22 {
 23     int id1 = l/len, id2 = r/len, ans = 0;
 24     if(id1==id2)//如果l,r在同一个块内,暴力枚举
 25     {
 26         for(int i = l; i <= r; i++)
 27               if(judge(a[i], d, p))
 28                   ans++;
 29     }else
 30     {
 31         for(int i = id1+1; i <= id2-1; i++)//把中间的块加起来
 32           ans+=block[i].cnt[d][p];
 33         for(int i = l; i <= (id1+1)*len && i <= n; i++)//暴力最左边的块
 34           if(judge(a[i], d, p))
 35             ans++;
 36         for(int i = id2*len+1; i <= r; i++)//暴力最右边的块
 37           if(judge(a[i], d, p))
 38             ans++;
 39     }
 40     return ans;
 41 }
 42 
 43 void update(int x, int y)
 44 {
 45     int tmp = a[x], id = (x-1)/len;//这里起初x少减了个1,WA了好多次忧伤。。。
 46     a[x] = y;
 47     for(int i = 1; i <= 10; i++)
 48     {
 49         block[id].cnt[i][tmp%10]--;
 50         tmp/=10;
 51     }
 52     tmp = a[x];
 53     for(int i = 1; i <= 10; i++)
 54     {
 55         block[id].cnt[i][tmp%10]++;
 56         tmp/=10;
 57     }
 58 }
 59 
 60 int main()
 61 {
 62     int T, d, p, m, x, y, l, r, id;
 63     char cmd;
 64     cin>>T;
 65     while(T--)
 66     {
 67         scanf("%d%d", &n, &m);
 68         memset(block, 0, sizeof(block));
 69         memset(a, 0, sizeof(a));
 70         for(int i = 1; i <= n; i++)
 71         {
 72             scanf("%d", &a[i]);
 73             id = (i-1)/len;
 74             int tmp = a[i];
 75             for(int j = 1; j <= 10; j++)//初始化块
 76             {
 77                 block[id].cnt[j][tmp%10]++;
 78                 tmp/=10;
 79             }
 80         }
 81         while(m--)
 82         {
 83             getchar();
 84             scanf("%c", &cmd);
 85             if(cmd == 'Q')
 86             {
 87                 int ans = 0;
 88                 scanf("%d%d%d%d", &l, &r, &d, &p);
 89                 ans = query(l, r, d, p);
 90                 printf("%d
", ans);
 91             }else
 92             {
 93                 scanf("%d%d", &x, &y);
 94                 update(x, y);
 95             }
 96         }
 97     }
 98 
 99     return 0;
100 }
 
原文地址:https://www.cnblogs.com/Penn000/p/5776567.html