poj3264------线段树

题目大意:

有N个点,Q次查询,每次查询区间内的最大值和最小值之差

思路: 线段树

代码:

#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX = 200000+5;
int N,Q,a[MAX];
int ansMin,ansMax;
struct Tree
{
    int l,r,mins,maxs;
}tree[4*MAX];
///建立线段树,cnt为节点角标,a[l]-a[r]建树
void build(int cnt,int l,int r)
{
    tree[cnt].l = l,tree[cnt].r = r;
    if(l==r)
    {
        tree[cnt].mins = tree[cnt].maxs = a[l];
        return;
    }
    int mid = (l + r)/2;
    build(2*cnt,l,mid);
    build(2*cnt+1,mid+1,r);
    ///回溯建立父节点
    tree[cnt].mins = min(tree[2*cnt].mins,tree[2*cnt+1].mins);
    tree[cnt].maxs = max(tree[2*cnt].maxs,tree[2*cnt+1].maxs);

}
///查询区间l-r的最大值和最小值
void query(int cnt,int l,int r)
{
    if(tree[cnt].mins>=ansMin&&tree[cnt].maxs<=ansMax)
        return;
    if(tree[cnt].l==l&&tree[cnt].r==r)
    {
        ansMax = max(tree[cnt].maxs,ansMax), ansMin = min(tree[cnt].mins,ansMin);
        return;
    }
    ///分三种情况讨论
    int mid = (tree[cnt].l+tree[cnt].r)/2;
    if(r<=mid)///在mid右端
        query(2*cnt,l,r);
    else if(l>mid)///在mid左端
        query(2*cnt+1,l,r);
    else///两端
    {
        query(2*cnt,l,mid);
        query(2*cnt+1,mid+1,r);
    }

}
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d%d",&N,&Q)!=EOF)
    {
        memset(tree,0,sizeof(tree));
        for(int i=1;i<=N;i++)
            scanf("%d",&a[i]);
        int left,right;
        build(1,1,N);
        for(int i=1;i<=Q;i++)
        {
            ansMin = 0x3f3f3f3f, ansMax = -1;
            scanf("%d%d",&left,&right);
            query(1,left,right);
            printf("%d\n",ansMax-ansMin);
        }
    }
    return 0;
}
时间: 2024-10-21 00:31:49

poj3264------线段树的相关文章

Balanced Lineup(POJ-3264)(线段树)

很基础的一道线段树的题,有个地方卡了我好久,我下面的这个代码所求的区间是左闭右开的,所以如果所求区间包括区间端点的话需要在右区间上+1 线段树是一种高效的数据结构,特点是求一个区间里的最小.最大值.      数据结构感觉像模板,但是其中的思想应该更值得我们学习,不过话说现在也没几个人能静下心去研究它的原理了吧.. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm>

POJ3264 Balanced Lineup RMQ 线段树

求区间内最大数和最小数的差,用两棵线段树,一个维护区间最大值,一个维护区间最小值. #include <stdio.h> #include <vector> #include <math.h> #include <string.h> #include <string> #include <iostream> #include <queue> #include <list> #include <algori

POJ3264——Balanced Lineup(线段树)

本文出自:http://blog.csdn.net/svitter 题意:在1~200,000个数中,取一段区间,然后在区间中找出最大的数和最小的数字,求这两个数字的差. 分析:按区间取值,很明显使用的线段树.区间大小取200000 * 4 = 8 * 10 ^5; 进行查询的时候,注意直接判断l, r 与mid的关系即可,一开始写的时候直接与tree[root].L判断,多余了, 逻辑不正确. #include <iostream> #include <stdio.h> #inc

POJ3264 Balanced Lineup 线段树 RMQ ST算法应用

Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 36813 Accepted: 17237 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John de

POJ-3264 Balanced Lineup(线段树)

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 47042   Accepted: 22071 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh

poj3264(线段树区间求最值)

题目连接:http://poj.org/problem?id=3264 题意:给定Q(1<=Q<=200000)个数A1,A2,```,AQ,多次求任一区间Ai-Aj中最大数和最小数的差. 线段树功能:区间求最值,O(logN)复杂度查询 #pragma comment(linker,"/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <stri

初学线段树(poj3264)

线段树是用来对一堆数据处理的树结构,它的核心思想是二分(一般都用递归实现). 树里需要存的是编号,和区间的左右,还有就是看题目需要了 二叉树特性:1:左子树编号是父树的2倍,右子树是父树的2倍加一 .              2:左子树l是父树的l,左子树的r是父树的(l+r)/2:右子树的l是父树的(l+r)/2 +1,右子树的r是父树的r 如图: 图是偷来的,推荐那个大佬的博客吧:http://www.cnblogs.com/TheRoadToTheGold/p/6254255.html

poj 3264 线段树

线段树太弱了,题目逼格一高连代码都读不懂,今天开始重刷线段树,每天一题,风格用kuangbin大神和以前的,两种都写一遍 RMQ做法:poj3264 1 /* 2 POJ 3264 Balanced Lineup 3 题目意思:给定Q(1<=Q<=200000)个数A1,A2,```,AQ, 4 多次求任一区间Ai-Aj中最大数和最小数的差 5 */ 6 #include<stdio.h> 7 #include<algorithm> 8 #include<iost

北大ACM暑期培训(1)——线段树,树状数组

本文出自:http://blog.csdn.net/svitter 今天ACM暑期实训开始了,今天讲述的内容是: 7.14  数据结构(一): 线段树,树状数组,二维线段树. 线段树:invertal tree (称为区间树更加合适) 作用:快速区间查询,用于解决区间统计的有关问题. 重点:同层节点不重叠. 每层最多有两个终止节点. 更新和进行区间分解的时间复杂度均为log(n); 方法:调用会多次使用递归更新插入查询: 空间:开空间的时候,一般情况下开4n大小,2*2log[n] - 1 <=

初识线段树

今天算是见到了线段树这玩意儿了,,, 这个线段树是一棵二叉树,树中的每一个结点表示了一个区间[a,b].每一个叶子节点表示了一个单位区间.对于每一个非叶结点所表示的结点[a,b],其左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]. 这个线段树可以使用指针来表示,也可以使用静态全局数组模拟(大小一般要开成节点的四倍哟O(∩_∩)O~). 其题目单节点更新.成端更新(需要用到延迟标记).区间合并.扫描线. 其常见操作如下:建立线段树(build).更新操作(u