本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题意:
题目链接:SDNU多校组队赛(第3,4场) - Virtual Judge
给你 n 个数,q 次询问,每次询问一个区间 [l, r],在这个区间里让你找可以构成三角形的最大周长。1 <= n <= 10^5
解题思路:
首先很容易想到对这 l - r 个数排序,然后从后相邻三个为一组往前找就行,但是询问区间都要排序时间复杂度太高,就可以用主席树来维护,可以通过求区间第k小来一个一个求出来,专门花费时间排序了,就直接logn查询,有些人可能有疑问了,那么长的序列从大到小三个一起慢慢枚举不会超时吗? 答案是不会的,因为斐波那契数列是极端不能形成三角形的序列,所以最多50次就可以查询出结果。
AC代码:
#include<bits/stdc++.h>
#define up(i, x, y) for(ll i = x; i <= y; i++)
#define down(i, x, y) for(ll i = x; i >= y; i--)
#define bug prllf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define IO ios::sync_with_stdio(false),cin.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-8;
const ll mod = 1e9 + 7;
const ll maxn = 1e5 + 7;
const double pi = acos(-1);
const ll inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
using namespace std;
int n, q, cnt, root[maxn * 40], a[maxn];
vector<int> v;
struct node
{
int l, r, sum;
}t[maxn * 40];
int getid(int x)
{
return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}
void update(int l, int r, int &x, int y, int pos)
{
t[++cnt] = t[y];
t[cnt].sum++;
x = cnt;
if(l == r) return ;
int mid = (l + r) >> 1;
if(pos <= mid) update(l, mid, t[x].l, t[y].l, pos);
else update(mid + 1, r, t[x].r, t[y].r, pos);
}
int query(int l, int r, int x, int y, int k)
{
if(l == r) return l;
int mid = (l + r) >> 1;
int sum = t[ t[y].l ].sum - t[ t[x].l ].sum;
if(sum >= k) return query(l, mid, t[x].l, t[y].l, k);
else return query(mid + 1, r, t[x].r, t[y].r, k - sum);
}
int main()
{
while(~scanf("%d %d", &n, &q))
{
v.clear();
cnt = 0;
up(i, 1, n)
{
scanf("%d", &a[i]);
v.push_back(a[i]);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
for(int i = 1; i <= n; i++)
{
update(1, n, root[i], root[i - 1], getid(a[i]));
}
int sp[5];
while(q--)
{
int loc = 0;
int f = 0;
int x, y; scanf("%d %d", &x, &y);
int all = y - x + 1;
for(int k = all; k >= 1; k--)
{
int tmp = v[ query(1, n, root[x - 1], root[y], k) - 1 ];
sp[++loc] = tmp;
if(loc == 3)
{
if(sp[2] + sp[3] > sp[1])
{
printf("%lld\n", (ll)sp[1] + sp[2] + sp[3]);
f = 1;
break;
}
else
{
sp[1] = sp[2];
sp[2] = sp[3];
loc = 2;
}
}
}
if(!f) puts("-1");
}
}
}