时间限制: 3 Sec 内存限制: 128 MB
提交: 155 解决: 34
[提交] [状态] [命题人:admin]
题目描述
N sticks are arranged in a row, and their lengths are a1,a2,...,aN.
There are Q querys. For i-th of them, you can only use sticks between li-th to ri-th. Please output the maximum circumference of all the triangles that you can make with these sticks, or print −1 denoting no triangles you can make.
输入
There are multiple test cases.
Each case starts with a line containing two positive integers N,Q(N,Q≤105).
The second line contains N integers, the i-th integer ai(1≤ai≤109) of them showing the length of the i-th stick.
Then follow Q lines. i-th of them contains two integers li,ri(1≤li≤ri≤N), meaning that you can only use sticks between li-th to ri-th.
It is guaranteed that the sum of Ns and the sum of Qs in all test cases are both no larger than 4×105.
输出
For each test case, output Q lines, each containing an integer denoting the maximum circumference.
复制样例数据
5 3
2 5 6 5 2
1 3
2 4
2 5
样例输出
13
16
16
[提交][状态]
题意:在[l,r]区间内算出最大的三角形周长,如果组不成三角形输出-1
思路:在每一个区间找出第一大,第二大,第三大,看能否组成三角形,不行则继续计算第二、三、四大,超过45左右,就可以不用计算了,因为按斐波那契数列的性质,超过该个数,数字大小超过1e9(三角形条件两边之和大于第三边,不成立的条件是两边之和小于等于第三边,斐波那契数列则属于不成立条件的极端等于)
用主席树来找第k大,是主席树的常用题
代码:
#include
using namespace std;
typedef long long ll;
const int mod = 998244353;
const int maxn = 1e5 + 100;
int n, q;
ll a[maxn], b[maxn];
int T[maxn], L[maxn << 5], R[maxn << 5], sum[maxn << 5];
int tot;
void build(int &rt, int l, int r) {
rt = ++tot;
sum[rt] = 0;
if (l == r) return;
int mid = (l + r) >> 1;
build(L[rt], l, mid);
build(R[rt], mid + 1, r);
}
void update(int &rt, int l, int r, int pre, int x) {
rt = ++tot;
L[rt] = L[pre];
R[rt] = R[pre];
sum[rt] = sum[pre] + 1;
if (l == r) return;
int mid = (l + r) >> 1;
if (x <= mid) update(L[rt], l, mid, L[pre], x);
else update(R[rt], mid + 1, r, R[pre], x);
}
int query(int s, int e, int l, int r, int k) {
if (l == r) return l;
int mid = (l + r) >> 1;
int res = sum[L[e]] - sum[L[s]];
if (k <= res) return query(L[s], L[e], l, mid, k);
else return query(R[s], R[e], mid + 1, r, k - res);
}
int main() {
while (~scanf("%d%d", &n, &q)) {
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
b[i] = a[i];
}
sort(b + 1, b + n + 1);
int k = unique(b + 1, b + n + 1) - b - 1;
tot = 0;
build(T[0], 1, k);
for (int i = 1; i <= n; i++) {
update(T[i], 1, k, T[i - 1], lower_bound(b + 1, b + k + 1, a[i]) - b);
}
int l, r;
while (q--) {
scanf("%d%d", &l, &r);
if (r - l + 1 < 3) {
printf("-1\n");
continue;
}
ll ans = -1;
int x = query(T[l - 1], T[r], 1, k, r - l + 1);
int y = query(T[l - 1], T[r], 1, k, r - l);
for (int i = r - l - 1; i >= 1; i--) {
int z = query(T[l - 1], T[r], 1, k, i);
if (b[y] + b[z] > b[x]) {
ans = b[x] + b[y] + b[z];
break;
}
x = y;
y = z;
}
printf("%lld\n", ans);
}
}
return 0;
}