hdu 1166 敌兵布阵 单点更新 树状数组 线段树 两种做法

题意中文题不用解释;

线段树:

#include <cstdio> 
#include <iostream> 
#define lson l , m , rt << 1//rt*2 
#define rson m + 1 , r , rt << 1 | 1//rt*2+1 
using namespace std;
const int maxn = 55555;

int sum[maxn<<2];
void PushUP(int rt) 
{
	sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
//rt代表树的编号 
void build(int l,int r,int rt) 
{
	if (l == r) 
	{
		scanf("%d",&sum[rt]);
		return ;
	}
	//一直递归下去找 
	int m = (l + r) >> 1;
	build(l , m , rt << 1);
	build(m + 1 , r , rt << 1 | 1);
	PushUP(rt);
}
void update(int p,int add,int l,int r,int rt) 
{
	//在p节点加上add 区间为l,r 
	if (l == r) 
	{
		sum[rt] += add;
		return ;
	}
	int m = (l + r) >> 1;
	if (p <= m) update(p , add , l , m , rt << 1);
	else update(p , add , m + 1 , r , rt << 1 | 1);
	PushUP(rt);
}
int query(int L,int R,int l,int r,int rt) 
{//LR代表需要查询的区间,lr代表被查询的区间 就是LR在lr中查,rt代表当前节点 
	if (L <= l && r <= R) 
	{
		return sum[rt];
	}
	int m = (l + r) >> 1;//(l+r)/2 
	int ret = 0;
	if (L <= m) ret += query(L , R , l , m , rt << 1);
	if (R > m) ret += query(L , R , m + 1 , r , rt << 1 | 1);
	return ret;
}
int main() 
{
	int T , n;
	scanf("%d",&T);
	for (int cas = 1 ; cas <= T ; cas ++) 
	{
		printf("Case %d:\n",cas);
		scanf("%d",&n);
		build(1 , n , 1);
		char op[10];
		while (scanf("%s",op)) 
		{
			if (op[0] == 'E') break;
			int a , b;
			scanf("%d%d",&a,&b);
			
			if (op[0] == 'Q') 
			printf("%d\n",query(a , b , 1 , n , 1));
			else if (op[0] == 'S') 
			update(a , -b , 1 , n , 1);
			else update(a , b , 1 , n , 1);
		}
	}
	return 0;
} 


树状数组

#include<iostream>
#define MAXD 100000
using namespace std;
int n,m,in[MAXD],a[MAXD]; 

int lowbit(int t)   
{   
	return t & ( t ^ ( t - 1 ) );   
}  
//求前n项和  
int sum(int end) 
{  
	int sum = 0; 
  	while(end > 0) 
  	{ 
		sum += in[end]; 
  		end -= lowbit(end); 
  	} 
  	return sum;  
}  
//增加某个元素的大小   
void pluss(int pos, int num) 
{ 
	while(pos <= n) 
	{ 
		in[pos] += num; 
		pos += lowbit(pos); 
	} 
}
int main()
{
	int T;
	scanf("%d",&T);
	for (int cas = 1 ; cas <= T ; cas ++) 
	{
		memset(in,0,sizeof(in));
		printf("Case %d:\n",cas);
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			int x;
			scanf("%d",&x);
			pluss(i,x);
		}
		char op[10];
		while (scanf("%s",op)) 
		{
			if (op[0] == 'E') break;
			int a , b;
			scanf("%d%d",&a,&b);			
			if (op[0] == 'Q') 
			printf("%d\n",sum(b)-sum(a-1));
			else 
			if (op[0] == 'S') 
			pluss(a,-b);
			else 
			pluss(a,b);
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值