Keen On Everything But Triangle

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_43298454/article/details/98118861

题目链接
题意:给你n个数,q次询问,每次询问一个区间 [l, r],任选三边组成三角形,边只能单次使用,求最大周长。

题解:算最大周长的思路是将 [l, r]的边进行排序,从大往小取边,如果不能构造出三角形就舍弃最长边,继续判断。
但是排序加上q次询问肯定会T,因此我们可以用主席树维护,可以通过查询第k大取边,时间复杂的是logn,慢慢枚举。
斐波那契数列是极端不能形成三角形的序列,所以最多47次就可以查询出结果。

AC_code:

//
//Write by Yuan Xilan on 2019...
//
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int maxn = 1e5 + 5;
int N, Q, ans;
vector < int >v;
int a[maxn], root[maxn * 40];

struct node {
	int l, r, sum;		//sum表示以该结点为根的子树所含数组内元素的个数。
} t[maxn * 40];

int get_id(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[++ans] = t[y];
	t[ans].sum += 1;
	x = ans;
	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);
}

void solve()
{
	while (~scanf("%d%d", &N, &Q))
	{
		if (N == -1)
			break;
		v.clear();
		ans = 0;
		for (int i = 1; i <= N; ++i)
		{
			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], get_id(a[i]));
		}
		int b[5];
		while (Q--)
		{
			int times = 0;
			bool flag = true;
			int x, y;
			scanf("%d%d", &x, &y);
			int k = y - x + 1;	//表示第k大
			for (; k >= 1; --k)
			{
				int tmp =
				    v[query(1, N, root[x - 1], root[y], k) - 1];
				b[++times] = tmp;
				if (times == 3)
				{
					if (b[2] + b[3] > b[1])
					{
						printf("%lld\n",(ll) b[1] + b[2] + b[3]);//注意这里不用longlong会炸
						flag = false;
						break;
					} else
					{
						b[1] = b[2];
						b[2] = b[3];
						times -= 1;
					}
				}
			}
			if (flag)
				puts("-1");
		}
	}
}

int main()
{
	solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43298454/article/details/98118861