因为给了上限,言外之意算法与数据的上限有关,猜测是数组,但想一想不可能,所以应该是权值线段树
综合一下,猜测应该是区间第K大,也就是主席树了
最暴力的做法:每次询问排序后查看是否有连续超过的数相同
Q:为什么要是超过的数相同呢?为什么不能在给一个数据呢?
A:这是区间的一半,排序后如果存在则相同的数必须为中位数,证明略
所以结论与之前的猜想一结合,就是求区间的中位数的个数是否超过,
这与权值线段树上一个点的值就是下标的个数的思想完全匹配,所以就是一颗主席树
#include<cstdio>
#include<iostream>
using namespace std;
const int N=4500000,M=3e5+5;;
int n,m,T,ans,rt[M];
struct A
{
int lc[N],rc[N],c[N],cnt;
void add(int &p,int l,int r,int x)
{
lc[++cnt]=lc[p],rc[cnt]=rc[p],c[cnt]=c[p]+1,p=cnt;
if(l==r) return;
int mid=l+r>>1;
if(mid>=x) add(lc[p],l,mid,x);
else add(rc[p],mid+1,r,x);
}
int kth(int p1,int p2,int l,int r,int k,int bz)
{
if(l==r) return c[p2]-c[p1]>bz?l:0; //判断是否>r-l+1>>1,bz表示标准
int mid=l+r>>1,xx=c[lc[p2]]-c[lc[p1]];
if(xx>=k) return kth(lc[p1],lc[p2],l,mid,k,bz);
return kth(rc[p1],rc[p2],mid+1,r,k-xx,bz);
}
}tree;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
int x; scanf("%d",&x);
rt[i]=rt[i-1],tree.add(rt[i],1,m,x);
} //建树
scanf("%d",&T);
while(T--)
{
int l,r; scanf("%d%d",&l,&r);
ans=tree.kth(rt[l-1],rt[r],1,m,r-l+2>>1,r-l+1>>1); //查找中位数
if(!ans) puts("no"); else printf("yes %d\n",ans);
}
return 0;
}