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

poj3368线段树

时间:2014-10-13 20:10:17      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   os   ar   for   sp   div   

题意:给出q次询问,求区间内最长的连续序列。 水题。

1.RMQ 求法 ,st算法 2.线段树,简单的区间合并

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
const int maxn = 111111;
const int INF = 99999999;
int Hash[maxn * 2];
int dp[maxn][20];
int ans;
int sum[maxn];
void init()
{
    for (int i = 0; i < ans; i++)
        dp[i][0] = sum[i];
    for (int j = 1; (1 << j) <= ans; j++){
        for (int i = 0; i + (1 << j) - 1 < ans; i++){
            dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
        }
    }
}

int ask(int l, int r)
{
    int k = 0;
    while ((1 << (k + 1)) <= r - l + 1) k++;
    return max(dp[l][k], dp[r + 1 - (1 << k)][k]);
}

int erfen(int a[], int key)
{
    int pos = -1;
    int l = 0; int r = ans - 1;
    while (l <= r){
        int mid = (l + r) >> 1;
        if (a[mid] <= key){
            pos = mid; l = mid + 1;
        }
        else r = mid - 1;
    }
    return pos;
}

int erfen1(int a[], int key)
{
    int pos = -1;
    int l = 0; int r = ans - 1;
    while (l <= r){
        int mid = (l + r) >> 1;
        if (a[mid] >= key){
            pos = mid; r = mid - 1;
        }
        else l = mid + 1;
    }
    return pos;
}
int main()
{
    int n, q;
    int Begin[maxn], End[maxn];
    int l, r;
    int a[maxn];
    while (scanf("%d", &n), n){
        scanf("%d", &q);
        for (int i = 0; i < n; i++)
            scanf("%d", &a[i]);
        a[n] = -INF;
        int start = 0;
        ans = 0;
        for (int i = 0; i < n; i++){
            Hash[i] = ans;
            if (a[i] != a[i + 1]){
                sum[ans] = i - start + 1;
                Begin[ans] = start; End[ans] = i;
                start = i + 1; ans++;
            }
        }
        init();
        for (int i = 0; i < q; i++){
            int ret = 0;
            scanf("%d%d", &l, &r);
            l--; r--;

            if (Hash[l] == Hash[r]){
                printf("%d\n", r - l + 1); continue;
            }
            int lpos = Begin[Hash[l] + 1]; int rpos = End[Hash[r] - 1];
            ret = max(ret, lpos - l); ret = max(ret, r - rpos);
            if (Hash[l] + 1 == Hash[r]){
                printf("%d\n", ret); continue;
            }
            ret = max(ret, ask(Hash[l] + 1, Hash[r] - 1));
            cout << ret << endl;

        }
    }
    return 0;
}

线段树

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
using namespace std;
typedef long long LL;

#define lson  l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 111111;
int a[maxn];
int sum[maxn << 2], lsum[maxn << 2], rsum[maxn << 2];
void up(int l, int r, int rt)
{
    lsum[rt] = lsum[rt << 1];
    rsum[rt] = rsum[rt << 1 | 1];
    sum[rt] = max(sum[rt << 1], sum[rt << 1 | 1]);
    int mid = (l + r) >> 1;
    int len = (r - l + 1);
    if (lsum[rt] == (len - (len >> 1))) if (a[mid] == a[mid + 1]) lsum[rt] += lsum[rt << 1 | 1];
    if (rsum[rt] == (len >> 1)) if (a[mid] == a[mid + 1]) rsum[rt] += rsum[rt << 1];
    if (a[mid] == a[mid + 1]) sum[rt] = max(sum[rt], rsum[rt << 1] + lsum[rt << 1 | 1]);
    sum[rt] = max(sum[rt], lsum[rt]); sum[rt] = max(rsum[rt], sum[rt]);
}

void build(int l, int r, int rt)
{
    if (l == r){
        lsum[rt] = rsum[rt] = sum[rt] = 1;
        scanf("%d", &a[l]); return;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    up(l, r, rt);
}

int ask(int L, int R, int l, int r, int rt)
{
    if (L <= l&&r <= R) return sum[rt];
    int ans1 = -1; int ans2 = -1; int ans = -1;
    int mid = (l + r) >> 1;
    if (L <= mid) ans1 = ask(L, R, lson);
    if (R > mid) ans2 = ask(L, R, rson);
    if (a[mid] == a[mid + 1]) ans = min(rsum[rt << 1], mid - L + 1) + min(lsum[rt << 1 | 1], R - mid);
    ans = max(ans, ans1); ans = max(ans, ans2);
    return ans;
}

int main()
{
    int n, q, l, r;
    while (cin >> n, n){
        cin >> q;
        build(1, n, 1);
        for (int i = 0; i < q; i++){
            scanf("%d%d", &l, &r);
            printf("%d\n", ask(l, r, 1, n, 1));
        }
    }
    return 0;
}

 

poj3368线段树

标签:style   blog   color   io   os   ar   for   sp   div   

原文地址:http://www.cnblogs.com/yigexigua/p/4022706.html

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