Hdu--5057(树状数组,空间优化,在线 / 离线)

2014-10-04 16:53:30

思路:这题是个很裸的线段树 or 树状数组题,因为加了内存限制而变得有点意思。参考了别人博客,有两种做法:

(1)在线做法:将树状数组中的c[]数组变为:c[]和re[],分别表示数量 / 32768的商 和 数量除以32768后的余数,也就是原先的c[i] = c[i] * 32768 + re[i]。而c[]用char表示,re用signed short来表示,- =真是机智啊!最后c[]数组应该开成这样:c[maxn][10][10]。

(2)离线做法:先把所有操作读进来,然后枚举每一位,这样只用开c[maxn][10]的数组,int型直接上~~~。

这里附(1)的做法代码:

 1 /*************************************************************************
 2     > File Name: 5057.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Sat 04 Oct 2014 03:11:35 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <queue>
16 #include <iostream>
17 #include <algorithm>
18 using namespace std;
19 #define lp (p << 1)
20 #define rp (p << 1|1)
21 #define getmid(l,r) (l + (r - l) / 2)
22 #define MP(a,b) make_pair(a,b)
23 typedef long long ll;
24 const int INF = 1 << 30;
25 const int maxn = 100010;
26 const int mod = 1 << 15;
27 
28 int T,N,M;
29 int A[maxn];
30 char c[maxn][10][10];
31 unsigned short re[maxn][10][10];
32 
33 int Lowbit(int x){
34     return x & (-x);
35 }
36 
37 void Update(int x,int d,int p,int v){
38     int tmp;
39     while(x <= N){
40         tmp = re[x][d][p] + v;
41         c[x][d][p] += tmp / mod;
42         re[x][d][p] = tmp % mod;
43         x += Lowbit(x);
44     }
45 }
46 
47 int Getsum(int x,int d,int p){
48     int res = 0;
49     while(x){
50         res += c[x][d][p] * mod + re[x][d][p];
51         x -= Lowbit(x);
52     }
53     return res;
54 }
55 
56 int main(){
57     char s[5];
58     int tem,l,r,d,p,x,y;
59     scanf("%d",&T);
60     while(T--){
61         scanf("%d%d",&N,&M);
62         memset(c,0,sizeof(c));
63         memset(re,0,sizeof(re));
64         for(int i = 1; i <= N; ++i){
65             scanf("%d",A + i);
66             tem = A[i];
67             for(int j = 0; j < 10; ++j){
68                 Update(i,j,tem % 10,1);
69                 tem /= 10;
70             }
71         }
72         for(int i = 1; i <= M; ++i){
73             scanf("%s",s);
74             if(s[0] == 'S'){
75                 scanf("%d%d",&x,&y);
76                 tem = A[x];
77                 for(int j = 0; j < 10; ++j){
78                     Update(x,j,tem % 10,-1);
79                     tem /= 10;
80                 }
81                 A[x] = y;
82                 for(int j = 0; j < 10; ++j){
83                     Update(x,j,y % 10,1);
84                     y /= 10;
85                 }
86             }
87             else{
88                 scanf("%d%d%d%d",&l,&r,&d,&p);
89                 printf("%d\n",Getsum(r,d - 1,p) - Getsum(l - 1,d - 1,p));
90             }
91         }
92     }
93     return 0;
94 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4006140.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值