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的责骂的.
中央情报局要研究敌人究竟演习什么战术,所以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条命令
每组数据第一行一个正整数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。
对于每个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 }