传送门: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; }