hdu 1166 敌军布阵

A - 敌兵布阵
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
 

 

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询问,输出一个整数并回车,表示询问的段中的总人数,这个数最多不超过1000000。
 

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
 

思路:用简单数组解此不断变化的数组会超时,so,我们需要跟快的算法!

数状数组解题代码:

View Code
 1 // File Name: /media/文档/源程序/实验室/6A.cpp
 2 // Author: sheng
 3 // Created Time: 2013年03月19日 星期二 21时02分05秒
 4 
 5 #include <iostream>
 6 #include <string.h>
 7 #include <cstdio>
 8 using namespace std;
 9 #define Max 50005
10 
11 int army[Max], n;
12 
13 int lowbit(int i)
14 {
15     return i&(-i);
16 }
17 
18 void Change(int i, int x)
19 {
20     while (i <= n)
21     {
22         army[i] += x;
23         i += lowbit(i);
24     }
25     return ;
26 }
27 
28 int sadd(int i)
29 {
30     int sum = 0;
31     while (i > 0)
32     {
33         sum += army[i];
34         i -= lowbit(i);
35     }
36     return sum;
37 }
38 
39 int main()
40 {
41     int i, j, x, t, bout = 1;
42     char instruct[16];
43     scanf("%d", &t);
44     while (t--)
45     {
46         memset(army, 0, sizeof(army));
47         scanf("%d", &n);
48         for (i = 1; i <= n; i++)
49         {
50             scanf ("%d", &x);
51             Change(i, x);
52         }
53         printf ("Case %d:\n", bout ++);
54         while (scanf("%s", instruct))
55         {
56             if (instruct[0] == 'E')
57                 break ;
58             scanf ("%d%d",&i, &j);
59             if (instruct[0] == 'A')
60                 Change(i, j);
61             else if (instruct[0] == 'S')
62                 Change(i, -j);
63             else printf("%d\n",sadd(j) - sadd(i - 1));
64         }
65     }
66     return 0;
67 
68 }

线段树解题代码:

View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<string.h>
  5 using namespace std;
  6 class Node
  7 {
  8 public:
  9     int l,r,mid;
 10     int count;    
 11 };
 12 Node tree[200024];
 13 int num[50024];
 14 class Tree
 15 {
 16 public:
 17       void Maketree( int l,int r,int cnt );
 18       void Add( int l,int r, int cnt);
 19       int Qestion( int l,int r,int cnt );    
 20 };
 21 void Tree::Maketree( int l,int r,int cnt )
 22 {
 23     if( l == r )
 24     {
 25         tree[cnt].l = tree[cnt].r = l;
 26         tree[cnt].mid = l;
 27         tree[cnt].count = num[l];    
 28         return ;
 29     }    
 30     else
 31     {
 32         tree[cnt].l = l;
 33         tree[cnt].r = r;
 34         tree[cnt].mid = ( l + r )>>1;
 35         Maketree( l , tree[cnt].mid , cnt*2 );
 36         Maketree( tree[cnt].mid +1 , r, cnt*2 +1 );
 37         tree[cnt].count = tree[cnt*2].count + tree[cnt*2+1].count;
 38     }
 39 }
 40 void Tree::Add( int n,int m, int cnt )
 41 {
 42      if( tree[cnt].l == n&&tree[cnt].r==n )
 43      {
 44           tree[cnt].count += m;
 45           return;        
 46      }    
 47      else
 48      {
 49          if( n > tree[cnt].mid )
 50          Add( n , m , cnt*2+1 );
 51          else Add( n , m ,cnt*2 );        
 52          tree[cnt].count += m; 
 53      }
 54 }
 55 int Tree::Qestion( int l,int r,int cnt )
 56 {
 57    if( l==tree[cnt].l&&r==tree[cnt].r )
 58       return tree[cnt].count;
 59    else
 60    {
 61        if( l > tree[cnt].mid )
 62          return Qestion( l, r, cnt*2+1 );
 63        else
 64        {
 65             if( r <= tree[cnt].mid )
 66               return Qestion( l , r ,cnt*2 );
 67             else
 68             {
 69                return Qestion( l , tree[cnt].mid, cnt*2 )+Qestion( tree[cnt].mid+1,r, cnt*2+1 );    
 70             }        
 71        }        
 72    }    
 73 }
 74 int main( )
 75 {
 76    int Case,n,l,r;
 77    char c[10];
 78    while( scanf( "%d",&Case )==1 )
 79    {
 80       Tree e;
 81       for( int i=1; i<=Case ; i++ )
 82       {
 83           printf( "Case %d:\n",i );
 84           scanf( "%d",&n );
 85           for( int j=1; j<= n; j++ )
 86             scanf( "%d",&num[j] );    
 87           e.Maketree( 1,n,1 );
 88           while( scanf( "%s",c ),c[0]!='E' )
 89           {
 90              scanf( "%d%d",&l,&r );
 91               if( c[0]=='A' )
 92                e.Add( l,r,1 );
 93               else if( c[0]=='S' ) 
 94                    e.Add( l , -1*r,1 );
 95               else printf( "%d\n",e.Qestion( l,r,1 ) );        
 96           }    
 97       }        
 98    }
 99    return 0;    
100 }

 

 

posted on 2013-03-21 18:57  圣手摘星  阅读(172)  评论(0编辑  收藏  举报

导航