2019杭电暑假多校训练第二场 Keen On Everything But Triangle(主席树)

【题目】

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1460    Accepted Submission(s): 344


 

Problem Description

 sticks are arranged in a row, and their lengths are .

There are  querys. For -th of them, you can only use sticks between -th to -th. Please output the maximum circumference of all the triangles that you can make with these sticks, or print  denoting no triangles you can make.

 

 

Input

There are multiple test cases.

Each case starts with a line containing two positive integers .

The second line contains  integers, the -th integer  of them showing the length of the -th stick.

Then follow  lines. -th of them contains two integers , meaning that you can only use sticks between -th to -th.

It is guaranteed that the sum of s and the sum of s in all test cases are both no larger than .

 

 

Output

For each test case, output  lines, each containing an integer denoting the maximum circumference.

 

 

Sample Input

 

5 3 2 5 6 5 2 1 3 2 4 2 5

 

 

Sample Output

 

13 16 16

【题意】

给出n个数,给m次查询,每查询,l,r区间,问区间内选三个值能组成三角形的最大周长是多少。

【题解】

维护区间内前K大,只需要枚举前46大左右就可以。先取第一大和第二大第三大,比较,若不能构成三角形,那么第二大,第三大,第四大在作比较.理由:若找前46个都不能找到三角形,那么前46个数至少符合Fibonacci数的递增方式,当达到n=46左右的Fibonacci数时就已经超出题目给的范围了。证毕。。。

【代码】

#include
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,m,sum[40*N],ls[40*N],rs[40*N],rt[N],sz,k,cnt;
ll a[N],b[N];
void up(int pre,int &o,int l,int r,int pos)
{
	o=++cnt;
	ls[o]=ls[pre];
	rs[o]=rs[pre];
	sum[o]=sum[pre]+1;
	if(l==r) return ;
	int mid=l+r>>1;
	if(pos<=mid)
	{
		up(ls[pre],ls[o],l,mid,pos);
	}
	else up(rs[pre],rs[o],mid+1,r,pos);
}
ll qu(int pre,int o,int l,int r)
{
	if(l==r) return b[l];
	int mid=l+r>>1;
	int cmp=sum[rs[o]]-sum[rs[pre]];
	//int cmp=sum[ls[o]]-sum[ls[pre]];
	if(cmp>=k) return qu(rs[pre],rs[o],mid+1,r);
	else
	{
		k-=cmp;
		return qu(ls[pre],ls[o],l,mid);
	}
}
void init()
{
	cnt=0;
	memset(sum,0,sizeof(sum));
	memset(ls,0,sizeof(ls));
	memset(rs,0,sizeof(rs));
	memset(rt,0,sizeof(rt));
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		init();
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			b[i]=a[i];
		}
		sort(b+1,b+1+n);
		sz=unique(b+1,b+1+n)-b-1;
		for(int i=1;i<=n;i++)
		{
			int j=lower_bound(b+1,b+1+sz,a[i])-b;
			up(rt[i-1],rt[i],1,sz,j);
		}
		while(m--)
		{
			int ql,qr;
			scanf("%d%d",&ql,&qr);
			if(qr-ql+1<3) printf("-1\n");
			else{
                ll val[5],cnt=0;
                int tmk=0;k=0;
                bool flag=0;
                k=1;
                tmk=1;
                val[++cnt]=qu(rt[ql-1],rt[qr],1,sz);
                k=2;
                tmk=2;
                val[++cnt]=qu(rt[ql-1],rt[qr],1,sz);
                while(tmk<=46&&tmk

 

你可能感兴趣的:(数据结构---主席树,2019杭电多校题解)