入手线段树 hdu1754

今天学习了线段树的三个基本操作 建树 更新 查找

先理解下什么是线段树就这个题目而言 如果我们用普通的数组去存放 然后依次遍历访问的话 时间太多了线段树利用了二分的思想 把数据以段的形式进行储存 这样在访问的时候 时间复杂度就下来了

上图就是线段树的一个简单的模型

创建线段树(初始化)】:

由于线段树是用二叉树结构储存的,而且是近乎完全二叉树的,所以在这里我使用了数组来代替链表上图中区间上面的红色数字表示了结构体数组中对应的下标。

在完全二叉树中假如一个结点的序号(数组下标)为 I ,那么 (二叉树基本关系)

I 的父亲为 I/2,

I 的另一个兄弟为 I/2*2 或 I/2*2+1

I 的两个孩子为 I*2 (左)   I*2+1(右)

这段来自其他同学的博客  这个是建树的基础 我们用标号来链接每个叶节点

struct node
{
	int maxx;
	int l,r;
}stu[maxn*4]; 这个结构体就是每一个线段树的一个叶 其中有左右节点以及本题需要的max值先说说建树操作把
int mid=(l+r)/2;
	stu[i].l=l;
	stu[i].r=r;既然利用到了二分的思想 那么 这几步是少不了的  
void buildtree(int i,int l,int r)//建树
{
	int mid=(l+r)/2;
	stu[i].l=l;
	stu[i].r=r;
	if(l==r)
	{
		stu[i].maxx=a[l];
		return;
	}
	buildtree(i*2,l,mid);//构建左子点
	buildtree(i*2+1,mid+1,r);//构建右子点
	stu[i].maxx=max(stu[i*2].maxx,stu[i*2+1].maxx);//在递归结束回溯的时候 把最大值返回
}
再说说数据的更新更新的话 先得二分找到目标位置 然后替换 最后还得依次更新最大值的数据
void updata(int i)//更新
{
	int l=stu[i].l;
	int r=stu[i].r;
	int mid=(l+r)/2;//二分咯
	if(l==r&&r==x)//x为目标id 当左右节点相同的时候 就是找到这个数的时候
	{
		stu[i].maxx=y;
		return;
	}
	if(l<=x&&x<=mid) updata(i*2);//向左找
	else updata(i*2+1);//向右找
	stu[i].maxx=max(stu[i*2].maxx,stu[i*2+1].maxx);//回溯的时候 更新max的数据
}
最后就是询问过程了找最大值的过程中 要把要求的区间分段 即分割成好几个小段 然后放在建好的书里面找
int que(int a,int b,int i)//查找
{
	int l=stu[i].l;
	int r=stu[i].r;
	int mid=(l+r)/2;
	if(l==a&&r==b) return stu[i].maxx;
	if(b<=mid) return que(a,b,i*2);//全在右边
	else if(a>mid) return que(a,b,i*2+1);//全在左边
	else return max(que(a,mid,i*2),que(mid+1,b,i*2+1));//需要分割的话 取分开的最大
}
上完整代码#include<cstdio>
#include<iostream>
#include<string.h>
using namespace std;
#define maxn 200010
struct node
{
	int maxx;
	int l,r;
}stu[maxn*4];
int a[maxn];
int n,m,x,y;
void buildtree(int i,int l,int r)//建树
{
	int mid=(l+r)/2;
	stu[i].l=l;
	stu[i].r=r;
	if(l==r)
	{
		stu[i].maxx=a[l];
		return;
	}
	buildtree(i*2,l,mid);
	buildtree(i*2+1,mid+1,r);
	stu[i].maxx=max(stu[i*2].maxx,stu[i*2+1].maxx);
}
void updata(int i)//更新
{
	int l=stu[i].l;
	int r=stu[i].r;
	int mid=(l+r)/2;
	if(l==r&&r==x)
	{
		stu[i].maxx=y;
		return;
	}
	if(l<=x&&x<=mid) updata(i*2);
	else updata(i*2+1);
	stu[i].maxx=max(stu[i*2].maxx,stu[i*2+1].maxx);
}
int que(int a,int b,int i)//查找
{
	int l=stu[i].l;
	int r=stu[i].r;
	int mid=(l+r)/2;
	if(l==a&&r==b) return stu[i].maxx;
	if(b<=mid) return que(a,b,i*2);
	else if(a>mid) return que(a,b,i*2+1);
	else return max(que(a,mid,i*2),que(mid+1,b,i*2+1));
}
int main()
{
    char z;
   	cin.sync_with_stdio(false);
    while(cin>>n>>m)
    {
    	for(int i=1;i<=n;i++) cin>>a[i];
    	buildtree(1,1,n);
    	while(m--)
    	{
    		cin>>z>>x>>y;
    		if(z==‘U‘)
    		{
    			updata(1);
    		}
    		else
    		{

    			cout<<que(x,y,1)<<endl;
    		}
    	}
    }
	return 0;
}
时间: 2024-08-09 04:44:14

入手线段树 hdu1754的相关文章

线段树---HDU1754 I hate it

这个题也是线段树的基础题,有了上一个题的基础,在做这个题就显得比较轻松了,大体都是一样的,那个是求和,这个改成求最大值,基本上思路差不多,下面是代码的实现 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 const int MAX = 200010 * 4; 8 int segment[MAX]; 9 //向上调整 10 void p

hdu1754 I Hate It (简单线段树应用)

题目连接:hdu1754 I Hate It 本题考查的是线段树的基本操作.如果不懂线段树的基本操作请移步:这里 这一题是我学完线段树后的第一道线段树的题,可以说是十分的基础,我刚学完就可以一遍AC.大家只要对线段树的基本操作有所了解,应该是可以轻松AC的. 代码如下: // 有效结点: 200000 // 深度达到:(lg200000)/(lg2) +1 约等于 19 // 其完全二叉树 总结点 个数为: (1<<19) - 1 个 #include <stdio.h> #def

【HDU1754】I Hate It(线段树)

update:单点替换 query:区间最值 1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <numeric> 6 #include <cctype> 7 #include <algorithm> 8 #include <cmath> 9 #include <ve

hdu1754 I Hate It(线段树)

题目意思: http://acm.hdu.edu.cn/showproblem.php?pid=1754 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. Input 本题目包含多组测试,请处理到文件结束. 在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分

hdu1754 线段树

1 //Accepted 7172 KB 515 ms 2 //基础线段树 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 using namespace std; 7 const int imax_n = 200005; 8 struct node 9 { 10 int l,r; 11 int tmax; 12 }f[imax_n*3]; 13 int a[imax_n]; 14 int

HDU1754(线段树)

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 51036    Accepted Submission(s): 20011 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要

HDU-1754 I Hate It(线段树、点变化+段查询---模板)

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 81735    Accepted Submission(s): 31442 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要

HDU1754 I HATE IT【线段树】

题面: Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. Input 本题目包含多组测试,请处理到文件结束. 在每个测试的第一行,有两个正整数 N 和 M ( 0 大致思路: 依然是一个裸的线段树,点修改+区间询问,不过要求和上一题不一样.这个题求的是区间最大值. 把树中存的数改

hdu1754 I hate it (线段树)

I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 55291 Accepted Submission(s): 21599 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一