hdu 1166 敌兵布阵(线段树OR树状数组)

 

去年学树状数组的时候用树状数组写过这题,如今学线段树,用线代树写了一次,发现线段树的代码好像更长,程序运行时间也比树状数组久

现在树状数组也忘光光了,,, (┬_┬)。。。

PS: 某渣看到以前的代码 真的是不舒服啊  吐槽一下自己

今天写的线段树:

 

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<limits.h>
using namespace std;
#define MAXN 50001

struct node
{
	int l,r;
	int sum;
}a[4*MAXN];

void Build(int l,int r,int n)// 构建线段树 
{
	a[n].l= l;
	a[n].r= r;
	a[n].sum= 0;
	if(l == r)
		return;
	int mid= (l + r) /2;
	Build(l, mid, 2*n);
	Build(mid + 1, r, 1+2*n);	
}

void Add(int num,int v, int n)
{
	if(v == a[n].l && v == a[n].r)
	{
		a[n].sum += num;
		return;
	}
	int mid= (a[n].l + a[n].r)/ 2;
	if(v<= mid)
		Add(num, v, 2*n);
	else 
		Add(num,v,1+ 2*n);
	a[n].sum= a[2*n].sum + a[2*n+1].sum; 	
}


void Sub(int num, int v, int n)
{
	if(v == a[n].l && v == a[n].r)
	{
		a[n].sum-= num;
		return;
	}
	int mid= (a[n].l +a[n].r)/ 2;
	if(v<= mid)
		Sub(num, v, 2*n);
	else 
		Sub(num,v,1+ 2*n);
	a[n].sum= a[2*n].sum + a[2*n+1].sum;
}

int Query(int l,int r, int n)
{
	if(l == a[n].l && r == a[n].r)
		return a[n].sum;
	int mid= ( a[n].l + a[n].r) /2;
	if(r<= mid)
		return Query(l, r, 2*n);
	else if(l> mid)
		return Query(l, r, 1+ 2*n);
	else
		return Query(l, mid, 2*n) + Query(mid + 1, r, 1+ 2*n);			
}

int main()
{
	int T;
	scanf("%d",&T);
	for(int t= 1; t<= T; t++)
	{
		int n;
		scanf("%d",&n);
		Build(1,n,1);
		int xixi;
		for(int i= 1; i<= n; i++)
		{
			scanf("%d",&xixi);
			Add(xixi,i,1);
		}
		char ch[10];
		int p,q;
		printf("Case %d:\n",t);
		while(scanf("%s",&ch)!=EOF)
		{
			if(ch[0]=='E')
				break;
		   	scanf("%d%d",&p,&q);
		    if(ch[0]=='A')
				Add(q, p, 1);
			else if(ch[0]=='S')
				Sub(q, p, 1);
			else
			{
				int sum= Query(p, q, 1);
				printf("%d\n",sum);
			}			
		}
	}
	return 0;
}


 

以前写的恶心树状数组:

 

#include<stdio.h>
#include<math.h>
#include<string.h>
int c[50010]={0};
int lowbit(int i)   
{  
    return i&(-i);  
}  
void add(int x,int delta,int n)
{
    for(int i=x; i<= n;i+=lowbit(i))
    c[i]+=delta;
}
int Getsum(int x)
{
int sum=0;
    for(int i=x; i> 0;i-=lowbit(i) )
        sum+=c[i];
    return sum;
}
int main()
{
int m,n,k;
scanf("%d",&m);
    for(k= 1;k<= m; k++)
    {memset(c,0,sizeof(c));
        int a;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
        scanf("%d",&a);
        add(i,a,n);
        }
        char s[10];
        getchar();
        int flog=0;
        while(scanf("%s",&s)!=EOF)
        {int x=0,y=0,sum;
            if(s[0]=='E')
                break;
            scanf("%d%d",&x,&y);
            if(s[0]=='A')
                add(x,y,n);
            else if(s[0]=='S')
                add(x,-y,n);
            else    if(s[0]=='Q')
            {
            if(flog==0)
            {printf("Case %d:\n",k);flog++;}
            sum=Getsum(y) - Getsum(x-1);
            printf("%d\n",sum);}
        }
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值