首页 > 代码库 > poj3368线段树

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|1const 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线段树