闲着无聊,写两个线段树发现类似点。

18 篇文章 0 订阅

Hdu 1166 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166

Hdu 1754 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754


线段树:1分为2,2分为4,4分为8,区间更新。

一个求和,一个求最大值。差不多吧。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
using namespace std;
struct node
{
	int s,l,r;
}a[500010];
void bulit(int n,int l,int r)
{
	a[n].s=0;
	a[n].l=l;
	a[n].r=r;
	if (l==r) return; 
	int m=(l+r)/2;
	bulit(n*2,l,m);
	bulit(n*2+1,m+1,r);
}
void insert(int n,int x,int y)
{
	a[n].s+=y;
	if (a[n].l==a[n].r)
		return;
	int m=(a[n].l+a[n].r)/2;
	if (x<=m)
		insert(n*2,x,y);
	else
		insert(n*2+1,x,y);
}
void change(int n,int x,int y)
{
	if (a[n].l==a[n].r)
	{
		a[n].s+=y;
		return;
	}
	int m=(a[n].l+a[n].r)/2;
	if (x<=m)
		change(n*2,x,y);
	else 
		change(n*2+1,x,y);
	a[n].s=a[2*n].s+a[2*n+1].s;
}
long long qsum(int n,int l,int r)
{
	if (a[n].l==l && a[n].r==r)
		return a[n].s;
	int m=(a[n].l+a[n].r)/2;
	if (r<=m)
		return qsum(n*2,l,r);
	else if (l>m)
		return qsum(n*2+1,l,r);
	else
		return qsum(n*2,l,m)+qsum(n*2+1,m+1,r);
}
int main()
{
	int T,n,i,j,k;
	char c[10];
	scanf("%d",&T);
	for (int cas=1;cas<=T;cas++)
	{
		printf("Case %d:\n",cas);
		scanf("%d",&n);
		bulit(1,1,n);
		for (i=1;i<=n;i++)
		{
			scanf("%d",&k);
			insert(1,i,k);
		}
		while (~scanf("%s",&c))
		{
			if (c[0]=='E') break;
			scanf("%d%d",&i,&j);
			if (c[0]=='A') change(1,i,j);
			if (c[0]=='S') change(1,i,-j);
			if (c[0]=='Q') printf("%lld\n",qsum(1,i,j));
		}
	}
	return 0;
}

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
using namespace std;
struct node
{
	int max,l,r;
}a[2000005];
int s;
void bulit(int n,int l,int r)
{
	a[n].max=0;
	a[n].l=l;
	a[n].r=r;
	if (l==r) return;
	int mid=(l+r)/2;
	bulit(n*2,l,mid);
	bulit(n*2+1,mid+1,r);
}
void insert(int n,int x,int y)
{
	if (a[n].max<y)
		a[n].max=y;
	if (a[n].l==a[n].r)
		return;
	int mid=(a[n].l+a[n].r)/2;
	if (x<=mid)
		insert(n*2,x,y);
	else
		insert(n*2+1,x,y);
	a[n].max=max(a[n*2].max,a[n*2+1].max);
}
int qmax(int n,int l,int r)
{
	if (a[n].l==l && a[n].r==r)
	{
		if (s<a[n].max)
			s=a[n].max;
		return s;
	}
	int mid=(a[n].l+a[n].r)/2;
	if (r<=mid)
		return qmax(n*2,l,r);
	else if (l>mid) 
		return qmax(n*2+1,l,r);
	else
		return max(qmax(n*2,l,mid),qmax(n*2+1,mid+1,r));
}
int main()
{
	int n,m,i,k;
	while (~scanf("%d%d",&n,&m))
	{
		bulit(1,1,n);
		for (i=1;i<=n;i++)
		{
			scanf("%d",&k);
			insert(1,i,k);
		}
		for (i=1;i<=m;i++)
		{
			getchar();
			char c;
			int q,w;
			s=0;
			scanf("%c%d%d",&c,&q,&w);
			if (c=='U') insert(1,q,w);
			if (c=='Q') printf("%d\n",qmax(1,q,w));
		}
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值