hdu1166 Enemy array tree array line segment tree template

enemy formation

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 110095    Accepted Submission(s): 46198


Problem Description
Country C's nemesis, Country A, is currently conducting military exercises, so country C's spy chief Derek and his subordinate Tidy are busy again. Country A has arranged N engineer camps along the coastline, and Derek and Tidy's task is to monitor the activities of these engineer camps. Due to the adoption of some advanced monitoring methods, country C has a clear grasp of the number of engineers in each engineer camp. The number of engineers in each engineer camp may change, and some personnel may be increased or decreased, but these cannot escape C. country surveillance.
The CIA wants to study what tactics the enemy is practicing, so Tidy has to report to Derek how many people there are in a certain continuous engineer camp. For example, Derek asked: "Tidy, immediately report how many people there are in the third to tenth camps. !" Tidy was about to start counting the total for the segment and reporting back. But the number of enemy camps often changes, and Derek asks different sections each time, so Tidy has to count each camp one by one, and soon exhausted, the faster Derek calculates Tidy Lai is more and more dissatisfied: "You fat boy, you are so slow, I will fire you!" Tidy thought: "You can do the math yourself, this is really a tiring job! I wish you would fire me! In desperation, Tidy had to call the computer expert Windbreaker for help. Windbreaker said: "Damn fat boy, I told you to do more acm problems and read more algorithm books. Now you have tasted the bitter fruit!" Tidy said: " I was wrong..." But Windbreaker had hung up. Tidy is very distressed, so he will really collapse, smart reader, can you write a program to help him do this work? However, if your program is not efficient enough, Tidy will still be scolded by Derek.
 

Input
The first line contains an integer T, indicating that there are T groups of data.
The first line of each set of data has a positive integer N (N<=50000), indicating that the enemy has N engineer camps, followed by N positive integers, the i-th positive integer ai represents the i-th engineer camp with ai at the beginning Individual (1<=ai<=50).
Next, there is one command per line, and the command has 4 forms:
(1) Add ij, i and j are positive integers, indicating that j people are added to the i-th camp (j does not exceed 30)
(2) Sub ij, i and j It is a positive integer, which means that the i-th camp is reduced by j people (j does not exceed 30);
(3) Query ij , i and j are positive integers, i<=j, which means that the total number of people from the i-th to the j-th camp is asked;
(4) End means the end, this command appears at the end of each group of data;
each group of data has a maximum of 40,000 commands
 

Output
For the i-th group of data, first output "Case i:" and carriage return.
For each Query query, output an integer and carriage return, indicating the total number of people in the query segment, which is kept within int.
 

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

Sample Output
 
  
Case 1:63359
 

Author
The first tree-like array


#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int n,a[50005];
char sh[15];

int lowbit(int i)
{
	return i&(-i);//树状数组最巧妙之处:i&(-i) 这个数的二进制取反加一
}

void update(int i,int val) //更新函数
{
	while(i<=n)
	{
		a[i]+=val;
		i+=lowbit(i);
	}
}

int sum(int i) //求和函数
{
	int sum=0;
	while(i>0)
	{
		sum+=a[i];
		i-=lowbit(i);
	}
	return sum;
}

int main()
{
	int i,val,t,x,y,zz=1;
	scanf("%d",&t);
	while(t--)
	{
		memset(a,0,sizeof(a));
		scanf("%d",&n);
		for(i=1;i<=n;i++)
		{
			scanf("%d",&val);
			update(i,val);
		}
		printf("Case %d:\n",zz++);
		while(scanf("%s",sh))
		{
			if(sh[0]=='E')
			break;
			scanf("%d%d",&x,&y);
			if(sh[0]=='A')
			update(x,y);
			else if(sh[0]=='S')
			update(x,-y);
			else
			printf("%d\n",sum(y)-sum(x-1));
			//两段区间和相减
		}
	}
	return 0;
}


第二种 线段树

//插点问线查询的线段树模板
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn(50030);
int ans;//全局变量 

struct node
{
	int left,right,sum;
}tree[4*maxn];

void maketree(int left,int right,int x)//创建线段树
{
	tree[x].left=left;
	tree[x].right=right;
	if(left==right)
	{
		scanf("%d",&tree[x].sum);
		return;
	}
	int mid=(left+right)>>1;//位运算,相当于除2
	maketree(left,mid,x<<1);//乘2
	maketree(mid+1,right,x<<1|1);//或运算(是将两个数字的二进制值的每一位进行或运算)
	tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum;
}

void query(int left,int right,int x,int l,int r)
{
	if(l<=left&&right<=r)
	{
		ans+=tree[x].sum;
		return;
	}
	int mid=(left+right)>>1;
	if(r<=mid)
	query(left,mid,x<<1,l,r);
	else if(l>mid)
	query(mid+1,right,x<<1|1,l,r);
	else
	{
		query(left,mid,x<<1,l,r);
		query(mid+1,right,x<<1|1,l,r);
	}
}

void update(int left,int right,int x,int pos,int add)
{
	if(left==right)
	{
		tree[x].sum+=add;
		return;
	}
	int mid=(left+right)>>1;
	if(pos<=mid)
	update(left,mid,x<<1,pos,add);
	else
	update(mid+1,right,x<<1|1,pos,add);
	tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum;
}

int main()
{
	int t,n,cnt,a,b;
	char str[10];
	cnt=1;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		maketree(1,n,1);//创建线段树
		printf("Case %d:\n",cnt++);
		while(scanf("%s",str))
		{
			if(str[0]=='E')
			break;
			scanf("%d%d",&a,&b);
			if(str[0]=='Q')
			{
				ans=0;
				query(1,n,1,a,b);//执行查询语句
				printf("%d\n",ans);
			}
			else if(str[0]=='A')
			update(1,n,1,a,b);//更新信息
			else
			update(1,n,1,a,-b);
		}
	}
	return 0;
}





Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324517863&siteId=291194637