2019杭电多校第二场 K Keen On Everything But Triangle HDU 6601 主席树

给了长度为n得序列
问 l r 区间最大得三角形周长
首先 ai 在 1e9 之内 所以最多跑50 个边就确定是否存在 合法三角形了
所以这里建主席树维护区间k值就好 记得主席树初始化除了建树 还要 tot = 0

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;

int n, m;
int a[maxn], b[maxn];
struct node {
	int lc,rc;
	int val;
} tree[maxn * 20];
int tot,root[maxn];

int build(int l, int r) {
	int p = ++ tot;
	if(l == r) {
		tree[p].val = 0;
		return p;
	}
	int mid = l + r >> 1;
	tree[p].lc = build(l, mid);
	tree[p].rc = build(mid + 1, r);
	tree[p].val = tree[tree[p].lc].val + tree[tree[p].rc].val;
	return p;
}

int ins(int now, int l, int r, int x, int val) {
	int p = ++ tot;
	tree[p] = tree[now];
	if(l == r) {
		tree[p].val += val ;
		return p;
	}
	int mid = l + r >> 1;
	if(x <= mid) 
		tree[p].lc = ins(tree[now].lc, l, mid, x, val);
	else 
		tree[p].rc = ins(tree[now].rc, mid + 1, r, x, val);
	tree[p].val = tree[tree[p].lc].val + tree[tree[p].rc].val;
	return p;
}

int ask(int p, int q, int l, int r, int k) {
	if(l == r) {
		return l;
	}
	int mid = l + r >> 1;
	int cnt = tree[tree[p].lc].val - tree[tree[q].lc].val ;
	if(k <= cnt) 
		return ask(tree[p].lc, tree[q].lc, l, mid, k);
	else 
		return ask(tree[p].rc, tree[q].rc ,mid + 1, r, k - cnt);
}

signed main(){
    while(~scanf("%d %d", &n, &m)){
		tot = 0;
        for(int i = 1; i <= n; i ++) scanf("%d", &a[i]), b[i] = a[i];
        sort(b + 1, b + 1 + n);
        int cnt = unique(b + 1, b + 1 + n) - b - 1;
        root[0] = build(1, cnt);
        for(int i = 1; i <= n; i++) {
            int pos = lower_bound(b + 1, b + 1 + cnt, a[i]) - b;
            root[i] = ins(root[i - 1], 1, cnt, pos, 1);
        }
        while(m -- ){
            int l, r;
            scanf("%d %d", &l, &r);
            int num = r - l + 1;
            if(num < 3) {
                printf("-1\n");
                continue;
            }
            long long ans = -1;
            for(int i = num; i >= max(3, num - 45); i -- ){
                int a1 = b[ask(root[r], root[l - 1], 1, cnt, i)];
                int b1 = b[ask(root[r], root[l - 1], 1, cnt, i - 1)];
                int c1 = b[ask(root[r], root[l - 1], 1, cnt, i - 2)];
                if(1ll * a1 + b1 > c1 && 1ll * a1 - b1 < c1) {
                    ans = 1ll * a1 + b1 + c1;
                    break;
                }
            }
            printf("%lld\n", ans);
        }
    } 
    return 0;
}
全部评论

相关推荐

感性的干饭人在线蹲牛友:🐮 应该是在嘉定这边叭,禾赛大楼挺好看的
点赞 评论 收藏
分享
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务