POJ 3264

第一次用指针写线段树,以前都是用数组写的。这道算是入门的线段树了。感觉用指针写,代码看起来更有艺术感,更优雅。对了,纪念下,这代码是一次AC的。


#include <stdio.h>
#include <stdlib.h>
#define MAX 99999999
struct cnode
{
	int left;
	int right;
	int Min;
	int Max;
	struct	cnode* pleft;
	struct  cnode* pright;
}*root;
void build(int s,int t,struct cnode* node)//建立线段树
{
 	node->left = s;
	node->right = t;
	node->Min = MAX;
	node->Max = -MAX;
	if(s == t)
	{
		node->pleft = NULL;
		node->pright = NULL;
		return;
	}
	node->pleft = (struct cnode*)malloc(sizeof(struct cnode));
	build(s,(s+t)>>1,node->pleft);
	node->pright = (struct cnode*)malloc(sizeof(struct cnode));
	build(((s+t)>>1)+1,t,node->pright);
}
void RMQ(int s,int t,int pos,int value,struct cnode* node)//建立RMQ的性质的线段树
{
	if(value > (node->Max))
	{
		(node->Max) = value;
	}
	if(value < node->Min)
	{
		node->Min=value;
	}
	if(node->pleft == NULL&&node->pright == NULL)
	{
		return;
	}
	if(node->pleft->left <= pos && node->pleft->right >= pos)
	{
		RMQ(s,(s+t)>>1,pos,value,node->pleft);	  
	}
	else if(node->pright->left <= pos && node->pright->right >= pos)
	{
		RMQ(((s+t)>>1)+1,t,pos,value,node->pright);
	}
}
int AnsMin;
int AnsMax;
void query(int s,int t,int qs,int qt,struct cnode* node)//往跟[s,t]有交集的地方递归下去,如果找到的区间是[s,t]的真子集,就停止递归下去(即返回)
{
	if((qs <= node->left) && (qt >= node->right))
	{	
		if(node->Max > AnsMax)
		{
			AnsMax =node->Max;
		}
		if(node->Min < AnsMin)
		{
			AnsMin = node->Min;
		}
		return;
	}
	int mid = (s+t)>>1;
    if(qs <= mid && qt > mid)
	{
		query(s,mid,qs,qt,node->pleft);
		query(mid+1,t,qs,qt,node->pright);
	}
	else if(mid >= qt)
	{
		query(s,mid,qs,qt,node->pleft);
	}
	else if(mid < qs)
	{
		query(mid+1,t,qs,qt,node->pright);
	}
}
int main()
{
	int n,m;
	int i;
	int value;
	int s,t;
	while(scanf("%d %d",&n,&m) != EOF)
	{
	  
	  root=(struct cnode*)malloc(sizeof(struct cnode));
		struct cnode* node = (struct cnode*)malloc(sizeof(struct cnode));
			root=node;
		build(1,n,node);
		for(i=1;i<=n;i++)
		{
			scanf("%d",&value);
			RMQ(1,n,i,value,node);
		}
		for(i=0;i<m;i++)
		{
			scanf("%d %d",&s,&t);
			AnsMin=MAX;
			AnsMax=-MAX;
			query(1,n,s,t,node);
			printf("%d\n",AnsMax-AnsMin);
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值