zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    ", ask(l, r, 1, n, 1));
            }
        }
        return 0;
    }
  • 相关阅读:
    网络适配器、网卡和网卡驱动
    PostgreSQL
    vsftp安装
    Ubuntu里面软件的安装与卸载
    ubuntu下查找某个文件的路径
    TCP的几个状态
    C++产生随机数
    ERROR Cannot determine the location of the VS Common Tools Folder
    小波变换C++实现(一)----单层小波变换
    离散卷积的计算
  • 原文地址:https://www.cnblogs.com/yigexigua/p/4022706.html
Copyright © 2011-2022 走看看