http://acm.hdu.edu.cn/showproblem.php?pid=1754&&线段树区间求最值

原创 2012年03月23日 14:43:10

I Hate It

Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13403 Accepted Submission(s): 5188


Problem Description
很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
这让很多学生很反感。

不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。

Input
本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。
学生ID编号分别从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。
当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。

Output
对于每一次询问操作,在一行里面输出最高成绩。

Sample Input
5 6 1 2 3 4 5 Q 1 5 U 3 6 Q 3 4 Q 4 5 U 2 9 Q 1 5

Sample Output
5 6 5 9
AC代码:
#include<iostream>
#include<string.h>
#include<algorithm>
#define N 200001
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define M(x,y) ((x+y)>>1)
using namespace std;
int maxx=-0xfffff;
typedef struct str
{
    int l;
    int r;
    int key;
}Node;
Node node[4*N];
int value[N];
int bulid(int t,int l,int r)
{
    node[t].l=l;
    node[t].r=r;
    if(l==r-1) return node[t].key=value[r];
    int mid=M(l,r);
   return node[t].key=max( bulid(L(t),l,mid),bulid(R(t),mid,r));
}
void update(int t,int l,int sum)
{
    if(node[t].l==node[t].r-1)
    {
        node[t].key=sum;
        return;
    }
    int mid=M(node[t].l,node[t].r);
    if(l>=mid) update(R(t),l,sum);
    else       update(L(t),l,sum);
	node[t].key=max(node[L(t)].key,node[R(t)].key);
 }
int Quary(int t,int l,int r)
{
   if(node[t].l==l&&node[t].r==r)  return node[t].key;
    int mid=M(node[t].l,node[t].r);
    if(l>=mid) return Quary(R(t),l,r);
    else
    {
        if(r<=mid) return Quary(L(t),l,r);
        else  return max(Quary(R(t),mid,r), Quary(L(t),l,mid));
	}
}
int main()
{
    int n,m;
    while(cin>>n>>m)
    {  
      
        for(int i=1;i<=n;++i)
         cin>>value[i];
		  bulid(1,0,n);
        char ch;
        for(int i=0;i<m;++i)
        {
            cin>>ch;
            int x,y;
            cin>>x>>y;
            if(ch=='Q') cout<<Quary(1,x-1,y)<<endl;
            else update(1,x-1,y);
        }
    }return 0;
}

动态:
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
typedef struct NODE
{
	int ld;
	int rd;
	struct NODE *lc,*rc;
	int key;
	NODE()
	{
		rc=lc=NULL;
		                                                                                                                                                                                                                                                                                                               
	}
}*Node,T;
int value[200001];
Node build(int a,int b)
{
	Node p=new T;
	p->ld=a;
	p->rd=b;
	if(a==b-1)
	{
		p->key=value[b];
		return p;
	}
	int mid=(a+b)/2;
	p->rc=build(mid,b);
	p->lc=build(a,mid);
	p->key=max(p->rc->key,p->lc->key);
	return p;
}
void update(Node p,int a,int b)
{
	if(p->ld==p->rd-1) 
	{
		p->key=b;
		return ;
	}
	int mid=(p->ld+p->rd)/2;
	if(a>=mid) update(p->rc,a,b);
	else update(p->lc,a,b);
	p->key=max(p->lc->key,p->rc->key);
}
int  Quary(Node p,int a,int b)
{
	if(p->ld==a&&p->rd==b) return p->key;
	int mid=(p->ld+p->rd)/2;
	if(a>=mid) return Quary(p->rc,a,b);
	else
	{
		if(b<=mid) return Quary(p->lc,a,b);
		else return max(Quary(p->rc,mid,b),Quary(p->lc,a,mid));
	}
}
void delet(Node p)//后序遍历删结点
{
	if(p->lc) delet(p->lc);
	if(p->rc) delet(p->rc);
	delete p;
}
int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<=n;++i)
			scanf("%d",&value[i]);
		  Node p=new T;
			 p=build(0,n);
		  for(int i=0;i!=m;++i)
		  {    getchar();
			  char ch;
			  int x,y;
			  scanf("%c%d%d",&ch,&x,&y);
			  if(ch=='Q')  printf("%d\n",Quary(p,x-1,y));
			  else  update(p,x-1,y);
		  }
		delet(p);
	}
	 
	return 0;
}


hdu1757 矩阵快速幂--

http://acm.hdu.edu.cn/showproblem.php?pid=1757 链接镇楼。。 给出
  • u014625544
  • u014625544
  • 2014年04月26日 16:13
  • 851

输入两个闭区间,求其交集,并集和差集(C++):

输入两个闭区间,求其交集,并集和差集(C++) #includeusing namespace std; int main(){ int a,b; int c,d; cout>a>>b; c...
  • yanglr2010
  • yanglr2010
  • 2013年05月31日 22:00
  • 1821

树状数组求区间极值

众所周知树状数组有着良好的特性:代码短,效率高。 但这样优良的数据结构不应只用于我们最初知道的,最基本的应用:单点修改,查询前缀和。 其应用可以更为广泛,如单点修改,查询区间极值。 由于区间极值无法像...
  • u012602144
  • u012602144
  • 2016年10月04日 16:58
  • 287

求数组的区间和

问题描述 就是输入n 然后输入n个数 下标为1~n 然后查询 查询次数不知道 但是以0 0 作为结束的标志 查询为l r 就是输出[l,r]区间的和 //这事朴素的求数组区间和的问题 import...
  • hjlovezhj
  • hjlovezhj
  • 2015年09月19日 09:42
  • 149

hdoj 5497 Inversion 【树状数组维护 区间逆序对】

Inversion Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total ...
  • chenzhenyu123456
  • chenzhenyu123456
  • 2015年10月04日 20:25
  • 672

树状数组求区间最大值

讲这个的博文已经不少了,但感觉不够详细不够通俗易懂,所以我尝试着更详细更通俗易懂的说一下我的理解。   这个算法只支持单点修改和区间查询最值。每一次维护和查询的时间复杂度都是O((logn)^2),但...
  • u010598215
  • u010598215
  • 2015年09月04日 10:42
  • 4867

NYOJ 1185 最大最小值(线段树—区间求最值)

 最大最小值 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 给出N个整数,执行M次询问。 对于每次询问,首先输入三个整数C、L、R:   ...
  • zwj1452267376
  • zwj1452267376
  • 2015年10月22日 13:16
  • 1222

BZOJ 2724 浅谈分块算法求区间众数

世界真的很大 分块算法大概算是一种在线的数据结构,和线段树作用差不多,但是却能维护一些线段树维护不了的信息。 线段树要求维护的信息必须要具备可合并性,就是说子区间的信息能够合并到大区间里,比如区间...
  • BerryKanry
  • BerryKanry
  • 2017年07月20日 10:29
  • 356

区间求交集算法

最近要去网易笔试,做往年笔试题的时候遇到一个比较难搞的,原题:有两个有序的集合,集合的每个元素都是一段范围,求其交集,例如集合{[4,8],[9,13]}和{[6,12]}的交集为{[6,8],[9,...
  • zyyloveweb
  • zyyloveweb
  • 2016年03月12日 21:46
  • 2629

伸展树splay之求区间极值

伸展树splay之求区间极值
  • chen1352
  • chen1352
  • 2016年09月29日 19:07
  • 285
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:http://acm.hdu.edu.cn/showproblem.php?pid=1754&&线段树区间求最值
举报原因:
原因补充:

(最多只允许输入30个字)