hdu 1754 I Hate It

hdu   1754   I Hate It

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

题目分析:二十万*五千的数据量,暴力就不要想了。这是个线段树入门水题,线段树是一种使用二叉树实现的奇特的数据结构,所以也具备了二叉树化N为lgN的能力,主要用来处理对一段区间上的特征值(如max、min等)的查询,是ACMer们数据结构方向上的必修课之一。此题甚水,只要懂线段树的基本知识,就能做了,具体可以参考我参考的那篇blog↓↓。

code:

#include<stdio.h>
#define inf 0x7fffffff
#define minf 0x80000000
struct stNode
{//left&right代表区间范围,此例程专门用作最大值与最小值的查询 
	int left,right,max,min;
}stn[600000];//树数组,记录方法同堆 
int parent[210000];//记录各叶子节点在树数组中的位置 
int max(int a,int b)
{
	return a>b?a:b;
}
int min(int a,int b)
{
	return a<b?a:b;
}
void build_tree(int i,int left,int right)
{
	stn[i].left=left;
	stn[i].right=right;
	if(left==right)
	{
		parent[left]=i;
		return;
	}
	build_tree(i<<1,left,(left+right)/2);
	build_tree((i<<1)+1,(left+right)/2+1,right);//此处教训:左右移运算符的优先级低于算术运算(+) 
}
void update_tree(int ri)
{
	if(ri==1)return;
	int fi=ri/2;
	int a=fi*2,b=fi*2+1;
	int maxi=max(stn[a].max,stn[b].max),mini=min(stn[a].min,stn[b].min);
	stn[fi].max=maxi;
	stn[fi].min=mini;
	update_tree(ri/2);
}
int query(int i,int l,int r,bool flag)//i为当前节点号,lr为待查左右区间,flag为找最大/小值:true/false 
{
	if(stn[i].left>r||stn[i].right<l)return flag?minf:inf;//边界控制 
	if(l==r||stn[i].max==stn[i].min)return stn[i].max;//到了单个点,max==min。
	if(stn[i].left>=l&&stn[i].right<=r)
	{
		return flag?stn[i].max:stn[i].min;
	} 
	if(flag)return max(query(i<<1,l,r,flag),query((i<<1)+1,l,r,flag));
	else return min(query(i<<1,l,r,flag),query((i<<1)+1,l,r,flag));
}
int main()
{
	int i,n,m,a[210000],p,q;
	char c[10];
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		build_tree(1,1,n);
		for(i=1;i<=n;i++)
		{
			scanf("%d",a+i);
			stn[parent[i]].max=stn[parent[i]].min=a[i];
			update_tree(parent[i]);
		}
		while(m--)
		{
			scanf("%s%d%d",c,&p,&q);
			if(c[0]=='Q')printf("%d\n",query(1,p,q,true));
			else
			{
				stn[parent[p]].max=stn[parent[p]].min=q;
				update_tree(parent[p]);
			}
		}
		//for(i=0;i<=9;i++)
		//{
			//printf("node[%d]:left=%d,right=%d,max=%d,min=%d\n",i,stn[i].left,stn[i].right,stn[i].max,stn[i].min);
		//}
	}
	return 0;
}

PS:参考了x314542916大神的blog,感谢赐教!

http://blog.csdn.net/x314542916/article/details/7837276

PSS:最难的query部分是我凭一己之力写的哦~






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值