HDU1166(分块)

 敌兵布阵

Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit  Status

Description

C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。 
中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:"我知错了。。。"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗?不过如果你的程序效率不够高的话,Tidy还是会受到Derek的责骂的. 

Input

第一行一个整数T,表示有T组数据。 
每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。 
接下来每行有一条命令,命令有4种形式: 
(1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30) 
(2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30); 
(3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数; 
(4)End 表示结束,这条命令在每组数据最后出现; 
每组数据最多有40000条命令 

Output

对第i组数据,首先输出“Case i:”和回车, 
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内。 

Sample Input

1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End 

Sample Output

Case 1:
6
33
59

这题在之前是用线段树做的,今天艾神讲分块,把艾神的分块做法贴一下
 1 //2016.8.12
 2 #include<iostream>
 3 #include<stdio.h>
 4 #include<algorithm>
 5 #include<string.h>
 6 #define kuai 230
 7 using namespace std;
 8 int arr[50005],n;
 9 int sum[305];
10 void add(int x,int y)
11 {
12     int belong=x/kuai;
13     sum[belong]+=y;
14     arr[x]+=y;
15     return;
16 }
17 int query(int x,int y)
18 {
19     int l=0,r=kuai-1,ans=0;
20     for (int i=0;i<kuai;i++,l+=kuai,r+=kuai)
21     {
22         int L,R;
23         L=max(l,x);
24         R=min(r,y);
25         if (L>R) continue;
26         if (L==l && R==r)
27             ans+=sum[i];
28         else
29         {
30             for (int j=L;j<=R;j++)
31                 ans+=arr[j];
32         }
33     }
34     return ans;
35 }
36 int main()
37 {
38     int t;
39     cin>>t;
40     for (int cas=1;cas<=t;cas++)
41     {
42         cin>>n;
43         for (int i=1;i<=n;i++)
44             scanf("%d",&arr[i]);
45         memset(sum,0,sizeof(sum));
46         for (int i=1;i<=n;i++)
47         {
48             int belong=i/230;
49             sum[belong]+=arr[i];
50         }
51         char ch[10];
52         printf("Case %d:\n",cas);
53         scanf("%s",ch);
54         while (ch[0]!='E')
55         {
56             int x,y;
57             scanf("%d%d",&x,&y);
58             if (ch[0]=='A')
59                 add(x,y);
60             else
61             if (ch[0]=='S')
62                 add(x,-y);
63             else
64             printf("%d\n",query(x,y));
65             scanf("%s",ch);
66         }
67     }
68 }

 

线段树做法。

  1 //2016-05-13
  2 #include<iostream>
  3 #include<string>
  4 #include<cstdio>  
  5 #include<cstring>  
  6 #include<algorithm>
  7 using namespace std;
  8 
  9 struct Node{
 10     int l, r, sum;
 11 }A[500050];
 12 
 13 void Pushup(int root)
 14 {
 15     A[root].sum = A[root<<1].sum + A[root<<1|1].sum;
 16     return ;
 17 }
 18 
 19 void Build(int l, int r, int root)
 20 {
 21     A[root].l = l;
 22     A[root].r = r;
 23     if(l == r)
 24     {
 25         scanf("%d", &A[root].sum);
 26         return;
 27     }
 28     int mid = (l + r)>>1;
 29     Build(l, mid, root<<1);
 30     Build(mid+1, r, root<<1|1);
 31     Pushup(root);
 32     return ;
 33 }
 34 
 35 void update(int l, int r, int root , int k)
 36 {
 37     if(l == A[root].l && r == A[root].r)
 38     {
 39         A[root].sum += k;
 40         return ;
 41     }
 42     int mid = (A[root].l + A[root].r) >> 1;
 43     if(r <= mid)
 44         update(l, r, root<<1, k);
 45     else if(l > mid)
 46         update(l, r, root<<1|1, k);
 47     else
 48     {
 49         update(l, mid, root<<1, k);
 50         update(mid+1, r, root<<1|1, k);
 51     }
 52     Pushup(root);
 53     return ;    
 54 }
 55 
 56 int Query(int l, int r, int root)
 57 {
 58     if(l == A[root].l && r == A[root].r)
 59         return A[root].sum;
 60     int mid = (A[root].l + A[root].r) >> 1;
 61     int ans = 0;
 62     if(r <= mid)
 63         ans += Query(l, r, root<<1);
 64     else if(l > mid)
 65         ans += Query(l, r, root<<1|1);
 66     else
 67         ans += Query(l, mid, root<<1) + Query(mid+1, r, root<<1|1);
 68     return ans;
 69 }
 70 
 71 int main ()
 72 {
 73     int T, cas, N;
 74     int l, k;
 75     string OP, A = "Add", S = "Sub", Q = "Query", E = "End";
 76     cas = 0;
 77     scanf("%d", &T);
 78     while(T--)
 79     {
 80         scanf("%d", &N);
 81         Build(1, N, 1);
 82         printf("Case %d:\n", ++cas);
 83         while(cin>>OP)
 84         {
 85             if(OP == A)
 86             {
 87                 scanf("%d %d", &l, &k);
 88                 update(l, l, 1, k);
 89             }
 90             else if(OP == S)
 91             {
 92                 scanf("%d %d", &l, &k);
 93                 update(l, l, 1, -k);
 94             }
 95             else if(OP == Q)
 96             {
 97                 scanf("%d %d", &l, &k);
 98                 printf("%d\n", Query(l, k, 1));
 99             }
100             else if(OP == E)
101                 break;
102         }
103     }
104     return 0;
105 }

 

树状数组做法。

 1 //2017-05-17
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 
 9 const int N = 50005;
10 int e[N], n;
11 
12 int lowbit(int x)
13 {
14     return x&-x;
15 }
16 
17 void add(int pos, int w)
18 {
19     while(pos <= n){
20         e[pos] += w;
21         pos += lowbit(pos);
22     }
23 }
24 
25 int sum(int pos)
26 {
27     int ans = 0;
28     while(pos > 0){
29         ans += e[pos];
30         pos -= lowbit(pos);
31     }
32     return ans;
33 }
34 
35 int main()
36 {
37     int T, a;
38     scanf("%d", &T);
39     for(int kase = 1; kase <= T; kase++){
40         scanf("%d", &n);
41         memset(e, 0, sizeof(e));
42         for(int i = 1; i <= n; i++)
43         {
44             scanf("%d", &a);
45             add(i, a);
46         }          
47         char op[10];
48         int x, y;
49         printf("Case %d:\n", kase);
50         while(scanf("%s", op)){
51             if(op[0] == 'Q'){
52                 scanf("%d%d", &x, &y);
53                 printf("%d\n", sum(y)-sum(x-1));
54             }else if(op[0] == 'A'){
55                 scanf("%d%d", &x, &y);
56                 add(x, y);
57             }else if(op[0] == 'S'){
58                 scanf("%d%d", &x, &y);
59                 add(x, -y);
60             }else if(op[0] == 'E')
61                   break;
62         }
63     }
64 
65     return 0;
66 }

 

转载于:https://www.cnblogs.com/Penn000/p/5766751.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值