传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3524
最近在学整体二分
在[l,r]中出现大于(r-l+1)次的一定是(r-l+2)/2小的
求k大再判断一下出现个数是否符合
rank又一次垫底……
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cctype>
#include<map>
#include<vector>
using namespace std;
const int maxn=500005;
int n,m;
map<int,vector<int> >M;
struct qes{
int x,y,z,ty,ind,cur,delta;
qes(int _x=0,int _y=0,int _z=0,int _ty=0,int _ind=0,int _cur=0,int _delta=0):
x(_x),y(_y),z(_z),ty(_ty),cur(_cur),delta(_delta),ind(_ind){}
}q[maxn*2];
int anss[maxn],cnt,mx,md,d[maxn];
int lowbit(int x){return x&-x;}
int get(int x){int ans=0;while(x)ans+=d[x],x-=lowbit(x);return ans;}
void updata(int x,int y){while(x<=n)d[x]+=y,x+=lowbit(x);}
bool part(qes &Q){
if(Q.ty==2){
if(Q.cur+Q.delta>Q.z-1)return true;
Q.cur+=Q.delta;Q.delta=0;return false;
}return Q.y<=md;
}
void solve(int lef,int rig,int l,int r){
if(lef>rig)return;
if(l==r){
for(int i=lef;i<=rig;i++)if(q[i].ty==2){
int L=lower_bound(M[l].begin(),M[l].end(),q[i].x)-M[l].begin();
int R=upper_bound(M[l].begin(),M[l].end(),q[i].y)-M[l].begin();
if(R-L>(q[i].y-q[i].x+1)/2)
anss[q[i].ind]=l;
}return;
}int mid=(l+r)>>1;md=mid;
for(int i=lef;i<=rig;i++){
if(q[i].ty==1&&q[i].y<=mid)updata(q[i].x,1);
if(q[i].ty==2)q[i].delta=get(q[i].y)-get(q[i].x-1);
}for(int i=lef;i<=rig;i++)
if(q[i].ty==1&&q[i].y<=mid)updata(q[i].x,-1);
int dv=stable_partition(q+lef,q+rig+1,part)-q-1;
solve(lef,dv,l,mid);
solve(dv+1,rig,mid+1,r);
}
int getint(){
int res=0;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c))res=res*10+c-'0',c=getchar();
return res;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int x=getint();mx=max(mx,x);
q[++cnt]=qes(i,x,0,1);M[x].push_back(i);
}for(int i=1;i<=m;i++){
int l=getint(),r=getint();
q[++cnt]=qes(l,r,(r-l+2)/2,2,++anss[0]);
}solve(1,cnt,0,mx);
for(int i=1;i<=anss[0];i++)printf("%d\n",anss[i]);
return 0;
}