LightOJ 1093 - Ghajini 线段树

http://www.lightoj.com/volume_showproblem.php?problem=1093

 

题意:给定序列,问长度为d的区间最大值和最小值得差最大是多少。

思路:可以使用线段树做,由于固定区间长度,还可以使用单调队列。

/** @Date    : 2016-12-06-18.39
  * @Author  : Lweleth (SoungEarlf@gmail.com)
  * @Link    : https://github.com/
  * @Version :
  */

#include<bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

struct yuu
{
    int l, r;
    int ma;
    int mi;
}tt[N << 2];

int a[N];

void pushup(int p)
{
    tt[p].ma = max(tt[p << 1].ma, tt[p << 1 | 1].ma);
    tt[p].mi = min(tt[p << 1].mi, tt[p << 1 | 1].mi);
}

void build(int l, int r, int p)
{
    tt[p].l = l;
    tt[p].r = r;
    tt[p].ma = 0;
    tt[p].mi = INF;
    if(l == r)
    {
        tt[p].ma = tt[p].mi = a[l];
        return ;
    }
    int mid = (l + r) >> 1;
    build(l , mid, p << 1);
    build(mid + 1, r, p << 1 | 1);
    pushup(p);
}

void updata(int l, int r, int v, int p)
{
    if(l <= tt[p].l && r >= tt[p].r)
    {
        return ;
    }
    int mid = (tt[p].l + tt[p].r) >> 1;
    if(l <= mid)
        updata(l, r, v, p << 1);
    if(r > mid)
        updata(l, r, v, p << 1 | 1);
    pushup(p);
}

PII query(int l, int r, int p)//直接返回pair会超时
{
    //cout <<tt[p].ma <<"~" <<tt[p].mi << endl;
    if(l <= tt[p].l && r >= tt[p].r)
        return MP(tt[p].ma, tt[p].mi);
    int mid = (tt[p].l + tt[p]. r) >> 1;
    PII ans;
    ans.fi = 0;
    ans.se = INF;
    if(l <= mid)
    {
        ans.fi = max(ans.fi, query(l, r, p << 1).fi);
        ans.se = min(ans.se, query(l, r, p << 1).se);
    }
    if(r > mid)
    {
        ans.fi = max(ans.fi, query(l, r, p << 1 | 1).fi);
        ans.se = min(ans.se, query(l, r, p << 1 | 1).se);
    }
    return ans;
}

int queryma(int l, int r, int p)
{
    if(l <= tt[p].l && r >= tt[p].r)
        return tt[p].ma;
    int mid = (tt[p].l + tt[p].r) >> 1;
    int ma = 0;
    if(l <= mid)
        ma = max(ma, queryma(l, r, p << 1));
    if(r > mid)
        ma = max(ma, queryma(l, r, p << 1 | 1));
    return ma;
}

int querymi(int l, int r, int p)
{
    if(l <= tt[p].l && r >= tt[p].r)
        return tt[p].mi;
    int mid = (tt[p].l + tt[p].r) >> 1;
    int mi = INF;
    if(l <= mid)
        mi = min(mi, querymi(l, r, p << 1));
    if(r > mid)
        mi = min(mi, querymi(l, r, p << 1 | 1));
    return mi;
}
int main()
{
    int T;
    int cnt = 0;
    cin >> T;
    while(T--)
    {
        int n, d;
        scanf("%d%d", &n, &d);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", a + i);
        }
        build(1, n, 1);
        //cout << query(2, 3, 1) << endl;
        int ma = 0;
        for(int i = 1; i + d - 1 <= n; i++)
        {
            //PII x = query(i, i + d - 1, 1);
            ma = max(queryma(i, i + d - 1, 1) - querymi(i, i + d - 1, 1), ma);
            //cout << ma <<endl;
        }
        printf("Case %d: %d\n", ++cnt, ma);
    }
    return 0;
}

posted @ 2016-12-06 23:18  Lweleth  阅读(234)  评论(0编辑  收藏  举报