hdu6601 Keen On Everything But Triangle【主席树】【2019 Multi-University Training Contest 2】

题意:

给你n个数字,q次查询,每次查询区间l,r之间可以组成三角形的最大周长是多少,没有就输出-1

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=6601

题解:

直接求区间第1大和第2大和第3大,不行组成就往下递推,最差情况就是成斐波那契数列,最多推49次

AC_code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 100010;
const int maxm = maxn*30;
int q, n, m, tot;
int a[maxn], t[maxn];
int rt[maxn], lson[maxm], rson[maxm], c[maxm];
void init_hash() {
    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 hashs(ll 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 num[55];
int main() {
    while(~scanf("%d %d", &n, &q)) {
        tot = 0;
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        init_hash();
        rt[n+1] = build(1, m);//建空树
        for(int i = n; i; i--) {
            int pos = hashs(a[i]);
            rt[i] = update(rt[i+1], pos, 1);
        }
        while(q--) {
            int l, r;
            scanf("%d %d", &l, &r);
            int len = (r - l + 1);
            ll ans = -1;
            while (len >= 3) {
                ll x1 = t[query(rt[l], rt[r + 1], len)];
                ll x2 = t[query(rt[l], rt[r + 1], len - 1)];
                ll x3 = t[query(rt[l], rt[r + 1], len - 2)];
                if (x1 < x2 + x3) {
                    ans = 1LL * x1 + 1LL * x2 + 1LL * x3;
                    break;
                }
                len--;
            }
            printf("%lld\n", ans);

    }



    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值