C 攀登山峰 2020计蒜之道决赛

https://nanti.jisuanke.com/t/49111

没想到这个t<=20怎么用。。。

因为t<=20,那么l,r这一区间最多只有t个位置能够数量>=v=(r-l+1)/t+1,也就是说直接上主席树,如果当前区间的数字总数<v就直接return,那么每次查询就最多向下跑t条链,复杂度是O(Mtlogn)的

#include<bits/stdc++.h>
using namespace std;

const int maxl=1e5+10;

int n,m,nn,tt,tot,mx;
int a[maxl],num[maxl],rt[maxl];
struct node
{
	int ls,rs,sum;
}tr[maxl*21];

inline void insert(int x,int &o,int l,int r)
{
	tr[++tot]=tr[o];o=tot;
	++tr[o].sum;
	if(l==r) return;
	int mid=(l+r)>>1;
	if(x<=mid)
		insert(x,tr[o].ls,l,mid);
	else 
		insert(x,tr[o].rs,mid+1,r);
}

inline void prework()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]),num[i]=a[i];
	sort(num+1,num+1+n);
	nn=unique(num+1,num+1+n)-num-1;
	for(int i=1;i<=n;i++)
		a[i]=lower_bound(num+1,num+1+nn,a[i])-num;
	for(int i=1;i<=n;i++)
	{
		rt[i]=rt[i-1];
		insert(a[i],rt[i],1,nn);
	}
}

inline void qry(int i,int j,int v,int l,int r)
{
	if(tr[j].sum-tr[i].sum<v)
		return;
	if(l==r)
	{
		mx=max(mx,l);
		return;
	}
	int mid=(l+r)>>1;
	qry(tr[i].ls,tr[j].ls,v,l,mid);
	qry(tr[i].rs,tr[j].rs,v,mid+1,r);
}

inline void mainwork()
{
	int l,r,t,v;num[0]=-1;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&l,&r,&t);
		v=(r-l+1)/t+1;mx=0;
		qry(rt[l-1],rt[r],v,1,nn);
		printf("%d\n",num[mx]);
	}
}

int main()
{
	prework();
	mainwork();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/109321957