hihocode #1299 打折机票

题意很简单就是给你两个数n和m,n表示有n张飞机票,m表示有m次查询,接下来n行,每行两个数,分别表示航班出发的时间和价格,接下来m行,每行两个数表示查询这两个数时间内航班最贵的价格。如果没有要求的机票就输出"None"。这道题是一道典型的RMQ问题,就是区间最值查询问题。这里提供两种解法。

1.线段树可以解决,而且是一道线段树的裸题。

//segment tree
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 100005;
int result;
struct tree
{
    int left;
    int right;
    int value;
}tree[N*4];
void build(int l, int r, int p)
{
    tree[p].left = l;
    tree[p].right = r;
    int mid = (l+r)/2;
    if(l == r)
    {
        tree[p].value = 0;
        return ;
    }
    build(l, mid, p*2);
    build(mid+1, r, p*2+1);
    tree[p].value = max(tree[p*2].value, tree[p*2+1].value);
}
void update(int t, int value, int p)
{
    int mid = (tree[p].left + tree[p].right) / 2;
    if(tree[p].left == tree[p].right)
    {
        tree[p].value = max(tree[p].value, value);
        return ;
    }
    if(t<=mid)
        update(t, value, p*2);
    else
        update(t, value, p*2+1);
    tree[p].value = max(tree[p*2].value, tree[p*2+1].value);

}
void query(int l, int r, int p)
{
    int mid = (tree[p].left + tree[p].right) / 2;
    if(tree[p].left == l && tree[p].right == r)
    {
        result = max(result, tree[p].value);
        return ;
    }
    if(r <= mid)
        query(l, r, p*2);
    else if(l > mid)
        query(l, r, p*2+1);
    else
    {
        query(l, mid, p*2);
        query(mid+1, r, p*2+1);
    }
}
int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    build(1, n, 1);
    for(int i=0; i<n; i++)
    {
        int t, v;
        scanf("%d%d", &t, &v);
        update(t, v, 1);
    }
    for(int i=0; i<m; i++)
    {
        int l, r;
        result = 0;
        scanf("%d%d", &l, &r);
        query(l, r, 1);
        if(result == 0)
            cout<<"None"<<endl;
        else
            cout<<result<<endl;
    }
    return 0;
}
2.用ST算法也可以解决。

算法分析:预处理时间复杂度为O(n*log(n)),但是查询的复杂度是O(1),预处理就是用一个二维数组data[a][b]表示从a到2^b内数的最值,然后用一个DP来更新所有的值,最后查询输出结果。

//RMQ解决区间最值问题
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int N = 100005;
int input[N];
int price[N][40];
void rmq(int num)
{
    int tmp = int(log(num*1.0) / log(2.0));
    for(int i=1; i<=num; i++)
        price[i][0] = input[i];
    for(int j=1; j<=tmp; j++)
        for(int i=1; i<=num; i++)
        {
            if(i+(1<<j) <= num)
                price[i][j] = max(price[i][j-1], price[i+(1<<(j-1))][j-1]);
        }
}
int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    memset(input, 0, sizeof(input));
    for(int i=0; i<n; i++)
    {
        int pos, pri;
        scanf("%d%d", &pos, &pri);
        input[pos] = max(pri, input[pos]);
    }
    rmq(N-1);
    for(int i=0; i<m ;i++)
    {
        int result, l, r;
        scanf("%d%d", &l, &r);
        int tmp = log((r-l+1)*1.0)/log(2.0);
        result = max(price[l][tmp], price[r-(1<<tmp)+1][tmp]);
        if(!result)
            cout<<"None"<<endl;
        else
            cout<<result<<endl;
    }
    return 0;
}




你可能感兴趣的:(RMQ,segment)