码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 1754 多个学生偷改成绩问最高分-线段树-(单点替换,区间最大值)

时间:2015-08-17 06:33:21      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:hdu   线段树   

题意:n个学生有初始成绩,现在有m个操作,(Q,a,b):询问区间学号为[a,b]的学生的最好成绩;(U,a,b):修改学号为a的学生的成绩为b,要你执行这m项操作。

分析:

单点更新,区间查询。确切的说是单点替换,区间查询。线段的典型用法之二。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm> 
using namespace std;
const int maxn=200000;
int n,m;
int mx[maxn*4+10];

void pushup(int rt)
{
	mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void creat(int l,int r,int rt)
{
	if(l==r){ // l==r 叶子节点,表示具体的某个学生
//		mx[rt]=0; //如果先建树再用upd更新初始值那么要在这里先赋初值,不然程序pushup()操作会出问题。赋任意值都行,因为输入初始值的时候会更新的 
		scanf("%d",&mx[rt]); //在这里建树的时候直接初始化也行 
		return;
	}
	int mid=(l+r)>>1; 
	creat(l,mid,rt<<1);
	creat(mid+1,r,rt<<1|1);
	pushup(rt);
}
void upd(int a,int x,int l,int r,int rt)
{
	if(l==r){   //叶子节点,如果找到了学生a,那么更新他的成绩
		mx[rt]=x;
		return;
	}
	int mid=(l+r)>>1; 
	if(a<=mid) 	upd(a,x,l,mid,rt<<1);  //如果a在左区间,就去左区间找到他,然后更新他的成绩
	else  upd(a,x,mid+1,r,rt<<1|1);        //如果在右区间,就去右区间找他
	pushup(rt);     //找到学生a更新他的成绩后要向上更新区间的最大值
}
int query(int a,int b,int l,int r,int rt)
{
	if(a<=l&&b>=r) return mx[rt];   //如果查询区间包含当前区间,那么直接返回区间最大值
	int mid=(l+r)>>1;        //不然就在当前区间的左子区间找最大值,右子区间找最大值然后返回左右的最大值
	int ret=0;
	if(a<=mid)
	ret=max(ret,query(a,b,l,mid,rt<<1));
	if(b>mid) 
	ret=max(ret,query(a,b,mid+1,r,rt<<1|1));
	return ret;
 } 
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF){
		creat(1,n,1);
//		for(int i=1;i<=n;i++){   //先建树再用更新操作更新初始值也可以,不过得在建树的时候先赋初值 
//			int a;
//			scanf("%d",&a);
//			upd(i,a,1,n,1);
//		}
		while(m--){
			char a[10]; 
			int b,c;
			scanf("%s%d%d",&a,&b,&c); //不能用%c,因为%c是不过滤空格和换行符的
			if(a[0]=='Q') printf("%d\n",query(b,c,1,n,1));
			else upd(b,c,1,n,1);
		}
	}
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 1754 多个学生偷改成绩问最高分-线段树-(单点替换,区间最大值)

标签:hdu   线段树   

原文地址:http://blog.csdn.net/ac_0_summer/article/details/47714603

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!