转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。
给你一个长度为n的序列s。
回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
其中a<b<c<d。
位置也从0开始标号。
http://www.lydsy.com/JudgeOnline/problem.php?id=2653
CLJ的题,强制在线处理了。
要求中位数最大,首先二分中位数,然后判断可行不可行。
判断X可行不可行,对于区间内的数,凡是>=X的标为1,否则为-1。这样的话,求一次最大区间和
如果大于等于0,则说明可行。
检验一下就很明白了。
这就是关键了,不过不能每次去暴力。快速求解子段和可以用线段树解决 ,但是对于不同的X,不可能建立多棵线段树
这就可以用主席树解决
对于初始的数,可以离散化,也可以不需要,直接排序,然后按从小到大依次建立主席树。
初始的话全为1,然后不断修改-1。有了之前的可持久化的基础,这步就很轻松了
然后就类似线段树一样,维护一个区间和,最大的左连续和,最大的右连续和。
结合在一起的时候,debug了下。。。。弱爆了
#include<iostream> #include<cstdio> #include<map> #include<cstring> #include<cmath> #include<vector> #include<algorithm> #include<set> #include<stack> #include<string> #include<ctime> #include<queue> #include<cassert> #define inf 1000000005 #define M 2560005 #define N 20005 #define maxn 210005 #define eps 1e-8 #define zero(a) fabs(a)<eps #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define pb(a) push_back(a) #define mp(a,b) make_pair(a,b) #define mem(a,b) memset(a,b,sizeof(a)) #define LL long long #define MOD 1000000007 #define sqr(a) ((a)*(a)) #define Key_value ch[ch[root][1]][0] #define test puts("OK"); #define pi acos(-1.0) #define lowbit(x) ((-(x))&(x)) #define HASH1 1331 #define HASH2 10001 #define C 240 #define vi vector<int> #define TIME 10 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; int a[N],n,q; int T[M],lson[M],rson[M],sum[M],lx[M],rx[M],tot=0; pair<int,int>h[N]; void Push_up(int root){ int l=lson[root]; int r=rson[root]; sum[root]=sum[l]+sum[r]; lx[root]=max(lx[l],sum[l]+lx[r]); rx[root]=max(rx[r],sum[r]+rx[l]); } int bulid(int l,int r){ int root=tot++; if(l==r){ lx[root]=rx[root]=sum[root]=1; return root; } int mid=(l+r)>>1; lson[root]=bulid(l,mid); rson[root]=bulid(mid+1,r); Push_up(root); return root; } int update(int root,int l,int r,int pos,int val){ int newroot=tot++; if(l==r){ sum[newroot]=lx[newroot]=rx[newroot]=val; return newroot; } int mid=(l+r)>>1; if(pos<=mid){ lson[newroot]=update(lson[root],l,mid,pos,val); rson[newroot]=rson[root]; root=lson[root]; } else{ rson[newroot]=update(rson[root],mid+1,r,pos,val); lson[newroot]=lson[root]; root=rson[root]; } Push_up(newroot); return newroot; } int query_all(int root,int L,int R,int l,int r){ if(l==L&&r==R) return sum[root]; int mid=(L+R)>>1; if(r<=mid) return query_all(lson[root],L,mid,l,r); else if(l>mid) return query_all(rson[root],mid+1,R,l,r); else return query_all(lson[root],L,mid,l,mid)+query_all(rson[root],mid+1,R,mid+1,r); } int query_left(int root,int L,int R,int l,int r){ if(l==L&&r==R) return lx[root]; int mid=(L+R)>>1; if(r<=mid) return query_left(lson[root],L,mid,l,r); else if(l>mid) return query_left(rson[root],mid+1,R,l,r); else return max(query_left(lson[root],L,mid,l,mid),query_all(lson[root],L,mid,l,mid)+query_left(rson[root],mid+1,R,mid+1,r)); } int query_right(int root,int L,int R,int l,int r){ if(l==L&&r==R) return rx[root]; int mid=(L+R)>>1; if(r<=mid) return query_right(lson[root],L,mid,l,r); else if(l>mid) return query_right(rson[root],mid+1,R,l,r); else return max(query_right(rson[root],mid+1,R,mid+1,r),query_all(rson[root],mid+1,R,mid+1,r)+query_right(lson[root],L,mid,l,mid)); } int check(int k,int a,int b,int c,int d){ int val=0; if(b+1<c) val+=query_all(T[k],0,n-1,b+1,c-1); val+=query_right(T[k],0,n-1,a,b); val+=query_left(T[k],0,n-1,c,d); return val>=0; } void debug(int root,int l,int r){ cout<<l<<" "<<r<<" "<<sum[root]<<endl; if(l!=r){ int m=(l+r)>>1; debug(lson[root],l,m); debug(rson[root],m+1,r); } } int main(){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); h[i]=mp(a[i],i); } sort(h,h+n); T[0]=bulid(0,n-1); for(int i=1;i<n;i++) T[i]=update(T[i-1],0,n-1,h[i-1].second,-1); scanf("%d",&q); int ans=0,p[4]; while(q--){ scanf("%d%d%d%d",&p[0],&p[1],&p[2],&p[3]); for(int i=0;i<4;i++) p[i]=(p[i]+ans)%n; sort(p,p+4); int low=0,high=n-1,mid,ret; while(low<=high){ mid=(low+high)>>1; if(check(mid,p[0],p[1],p[2],p[3])){ low=mid+1; ret=mid; } else high=mid-1; } ans=h[ret].first; printf("%d\n",ans); } return 0; }