HDU-6601 Triangular Chairman Tree Fibonacci Sequence

Give the length of n sides, ask q times, and answer each question about the maximum perimeter of the triangle that can be formed.

n and q are both 1 e 5 1e5The range of 1 e 5 .


First think about how to find the largest perimeter triangle for an array.

It is easy to think of it in order, enumerate N-2 times from large to small, and check whether the three sides can form a triangle each time. If not, then the largest side has no other side that can be grouped with him. (Other sides Are smaller). If the first feasible one is encountered, then it is the three sides of the triangle with the largest circumference.

The above algorithm is O (N log N) O(NlogN)O ( N l o g N ) , but also sorting, directly used to solve multiple-question questions is obviously not good, the complexity isO (QN log N) O(QNlogN)O ( Q N l o g N )

For enumeration from large to small, it is easy to think of using the chairman tree to maintain each O (log N) O(logN)O ( l o g N ) to get the k-thlargest value, the complexity is stillO (QN log N) O(QNlogN)O ( Q N l o g N )

But in fact, we don't need to enumerate N times to know the result.

Here we need to introduce ainsight

Suppose there is a very long array, and any three sides can not form a triangle. One conclusion is that the Fibonacci sequence (each item is equal to the sum of the first two items). But the Fibonacci sequence has grown very fast, surpassing 1e 9 1e9 at 45th place.1e9

So, give a set in the range 1e 9 1e9If the number of 1 e 9 exceeds 44, then there must be a number that breaks the Fibonacci sequence, which is equivalent to that there must be three sides that can form a triangle.

In this question, enumerate the largest 44 numbers in the interval in descending order. Check whether a triangle can be formed, and the largest one must be found. And the complexity is reduced to o (44 Q log N) o(44QlogN)o ( 4 4 Q l o g N )

This way, you can pass, the chairman tree constant is not afraid at all. (If you like to be faster, you can also hand-write the line segment tree to maintain the maximum number of 44...)

#define _debug(x) cerr<<#x<<" = "<<x<<endl

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
//const int MAXN = 3000 + 59;
const ll MOD = 998244353;
const int MAXN = 100015;

const int M = MAXN * 30;
int n, q, m, tot;
int a[MAXN], t[MAXN];
int T[MAXN], lson[M], rson[M], c[M];

void Init_hush() {
    
    
    for (int i = 1; i <= n; i++)
        t[i] = a[i];
    sort(t + 1, t + 1 + n);
    m = unique(t + 1, t + 1 + n) - t - 1;
}

int build(int l, int r) {
    
    
    int root = tot++;
    c[root] = 0;
    if (l != r) {
    
    
        int mid = (l + r) >> 1;
        lson[root] = build(l, mid);
        rson[root] = build(mid + 1, r);
    }
    return root;
}

int hush(int x) {
    
    
    return lower_bound(t + 1, t + 1 + m, x) - t;
}

int update(int root, int pos, int val) {
    
    
    int newroot = tot++, tmp = newroot;
    c[newroot] = c[root] + val;
    int l = 1, r = m;
    while (l < r) {
    
    
        int mid = (l + r) >> 1;
        if (pos <= mid) {
    
    
            lson[newroot] = tot++;
            rson[newroot] = rson[root];
            newroot = lson[newroot];
            root = lson[root];
            r = mid;
        } else {
    
    
            rson[newroot] = tot++;
            lson[newroot] = lson[root];
            newroot = rson[newroot];
            root = rson[root];

            l = mid + 1;
        }
        c[newroot] = c[root] + val;
    }
    return tmp;
}

int query(int left_root, int right_root, int k) {
    
    
    int l = 1, r = m;
    while (l < r) {
    
    
        int mid = (l + r) >> 1;
        if (c[lson[left_root]] - c[lson[right_root]] >= k) {
    
    
            r = mid;
            left_root = lson[left_root];
            right_root = lson[right_root];
        } else {
    
    
            l = mid + 1;
            k -= c[lson[left_root]] - c[lson[right_root]];
            left_root = rson[left_root];
            right_root = rson[right_root];
        }
    }
    return l;
}


ll Seg_k(int l, int r, int k) {
    
    
    return 1ll * t[query(T[l], T[r + 1], k)];
}

ll chek(int mid, int AskL, int AskR) {
    
    
    ll e1 = Seg_k(AskL, AskR, mid);
    ll e2 = Seg_k(AskL, AskR, mid - 1);
    ll e3 = Seg_k(AskL, AskR, mid - 2);

    if (e2 + e3 > e1) {
    
    
        return e1 + e2 + e3;
    } else {
    
    
        return -1;
    };
}



int main() {
    
    

    int tmp = 0;
    ll ans = 0;

    while (scanf("%d%d", &n, &q) == 2) {
    
    
        tot = 0;
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        Init_hush();
        T[n + 1] = build(1, m);
        for (int i = n; i; i--) {
    
    
            int pos = hush(a[i]);
            T[i] = update(T[i + 1], pos, 1);
        }
        while (q--) {
    
    
            int askl, askr;
            scanf("%d%d", &askl, &askr);
            int r = askr - askl + 1;
            int l = max(3, r - 48);
            ans = -1;

            for (int i = r; i >= l; i--) {
    
    
                ans = chek(i, askl, askr);
                if (ans > 0)break;
            }

            printf("%lld\n", ans);

        }
    }
    return 0;
}

/*




 */

Guess you like

Origin blog.csdn.net/Tighway/article/details/97159590