poj3368线段树

题意:给出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;

}

 

你可能感兴趣的:(poj)