[COGS 36]优雅的线段树(求和问题)

解题报告

题面见COGS
分析:这道题,又双叒叕是区间操作,果断线段树啊。刚刚跟某人@dch探(si)讨(bi)关于线段树大法好还是二叉索引树大法好的问题,肯定线段树大法好啦!!!
话说二叉索引树是什么鬼啦,太难了,%dch,%jjq。
线段树大法好!!!

#include <iostream>
#include <cstdio>
#define LL long long
using namespace std;
const int MX = 10005;
int n, m;
int num[MX];
struct node{
	int le, ri;
	LL sum;
}tree[MX*4];
inline int leftt(int a)
{
	return a<<1;
}
inline int rightt(int a)
{
	return (a<<1)^1;
}
inline int mid(int a,int b)
{
	return (a+b)>>1;
}
void biu(int cur,int l,int r)
{//建树
	if(l==r)
	{
		tree[cur].sum=num[l];
		tree[cur].le=tree[cur].ri=l;
		return;
	}
	else
	{
		biu(leftt(cur),l,mid(l,r));
		biu(rightt(cur),mid(l,r)+1,r);
		tree[cur].sum=tree[leftt(cur)].sum+tree[rightt(cur)].sum;
		tree[cur].le=l;
		tree[cur].ri=r;
	}
	return;
}
inline LL ask(int cur, int l, int r)
{//查询
	if(l==tree[cur].le&&r==tree[cur].ri)
	{
		return tree[cur].sum;
	}
	else
	{
		if(r<=tree[leftt(cur)].ri)
			return ask(leftt(cur),l,r);
		else if(l>=tree[rightt(cur)].le)
			return ask(rightt(cur),l,r);
		else
			return ask(leftt(cur),l,tree[leftt(cur)].ri)+ask(rightt(cur),tree[rightt(cur)].le,r);
	}
}
inline int get_num()
{
	int ans=0;
	char tmp;
	tmp=getchar();
	while(tmp<'0'||tmp>'9')	tmp=getchar();
	while(tmp<='9'&&tmp>='0')
	{
		ans=ans*10+tmp-48;
		tmp=getchar();
	}
	return ans;
}
int main()
{
	//freopen("sum.in","r",stdin);
	//freopen("sum.out","w",stdout);
	int x, y;
	n=get_num();
	LL tmp=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&num[i]);
	}
	biu(1,1,n);
	m=get_num();
	for(int i=1;i<=m;i++)
	{
		x=get_num();
		y=get_num();
		tmp=ask(1,x,y);
		cout<<tmp<<"\n";
	}
	return 0;
}

 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理