• bzoj2653: middle


    首先,对于每个询问,我们二分答案

    然后对于序列中大于等于中位数的数,我们把它们置为1,小于中位数的数,置为-1

    那么如果一个区间和大于等于0,那么就资磁,否则就不滋磁

    这个区间和呢,我们可以用主席树维护前缀和

    [c,d]上的最大前缀和减去[a-1,b-1]上的最小前缀和,就是所有可用区间的最大区间和

    这样要求主席树支持区间修改,正好之前没写过(捂脸),练一下

    复杂度O(nlog^2n)

    (如果不资磁区间修改的话,也可以通过维护最大/小连续和的那套理论,达到同样的效果(好像所有题解都是这么做的))

    (当然首先要离散化……)

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #define N 23333
    
    using namespace std;
    inline int read(){
    	int ret=0;char ch=getchar();
    	while (ch<'0'||ch>'9') ch=getchar();
    	while ('0'<=ch&&ch<='9'){
    		ret=ret*10-48+ch;
    		ch=getchar();
    	}
    	return ret;
    }
    
    struct STnode{
    	int ls,rs;
    	int maxv,minv;
    	int tag;
    };
    
    int n,root[N];
    struct SegmentTree{
    	STnode t[12333666];
    	int size;
    	inline int newnode(int x){t[++size]=t[x];return size;}
    	void PushUp(int x){
    		t[x].maxv=max(t[t[x].ls].maxv,t[t[x].rs].maxv);
    		t[x].minv=min(t[t[x].ls].minv,t[t[x].rs].minv);
    	}
    	void add(int &x,int delta){
    		x=newnode(x);
    		t[x].maxv+=delta;t[x].minv+=delta;t[x].tag+=delta;
    	}
    	void PushDown(int x){
    		if (!t[x].ls) t[x].tag=0;
    		if (t[x].tag){
    			add(t[x].ls,t[x].tag);add(t[x].rs,t[x].tag);
    			t[x].tag=0;
    		}
    	}
    	void build(int x,int l,int r){
    		t[x].tag=t[x].ls=t[x].rs=0;
    		if ((t[x].minv=l)==(t[x].maxv=r)) return;
    		int mid=(l+r)/2;
    		build(t[x].ls=++size,l,mid);
    		build(t[x].rs=++size,mid+1,r);
    	}
    	int clear(){build(size=1,1,n);return 1;}
    	void modify(int &x,int L,int R,int l,int r,int delta){
    		PushDown(x);
    		if (l<=L&&R<=r){add(x,delta);return;}
    		x=newnode(x);
    		int mid=(L+R)/2;
    		if (l<=mid) modify(t[x].ls,L,mid,l,r,delta);
    		if (r>mid) modify(t[x].rs,mid+1,R,l,r,delta);
    		PushUp(x);
    	}
    	int qmin(int x,int L,int R,int l,int r){
    		PushDown(x);
    		if (l<=L&&R<=r) return t[x].minv;
    		int mid=(L+R)/2;
    		if (r<=mid) return qmin(t[x].ls,L,mid,l,r);
    		if (l>mid) return qmin(t[x].rs,mid+1,R,l,r);
    		return min(qmin(t[x].ls,L,mid,l,r),qmin(t[x].rs,mid+1,R,l,r));
    	}
    	int qmax(int x,int L,int R,int l,int r){
    		PushDown(x);
    		if (l<=L&&R<=r) return t[x].maxv;
    		int mid=(L+R)/2;
    		if (r<=mid) return qmax(t[x].ls,L,mid,l,r);
    		if (l>mid) return qmax(t[x].rs,mid+1,R,l,r);
    		return max(qmax(t[x].ls,L,mid,l,r),qmax(t[x].rs,mid+1,R,l,r));
    	}
    } st;
    
    int query(int a,int b,int c,int d){
    	int l=1,r=n+1,mid;
    	while (l+1<r){
    		mid=(l+r)/2;
    		int tmpr=st.qmax(root[mid],1,n,c,d);
    		int tmpl=st.qmin(root[mid],1,n,max(a-1,1),b-1);
    		if (a==1) tmpl=min(tmpl,0);
    		if (tmpr-tmpl>=0) l=mid;
    		else r=mid;
    	}
    	return l;
    }
    
    
    int a[N];
    struct num{
    	int value,pos;
    	num(){}
    	num(int _value,int _pos):value(_value),pos(_pos){}
    } tt[N];
    inline bool operator <(const num &x,const num &y){
    	return x.value<y.value;
    }
    
    int main(){
    	n=read();
    	for (int i=1;i<=n;++i) tt[i]=num(a[i]=read(),i);
    	sort(tt+1,tt+n+1);
    	
    	root[1]=st.clear();
    	for (int i=1;i<n;++i)
    		st.modify(root[i+1]=root[i],1,n,tt[i].pos,n,-2); 
    	
    	int lastans=0,q[4];
    	for (int Q=read();Q;Q--){
    		for (int k=0;k<4;++k) q[k]=(read()+lastans)%n+1;
    		sort(q,q+4);
    		lastans=tt[query(q[0],q[1],q[2],q[3])].value;
    		printf("%d
    ",lastans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    单调队列 POJ 2823
    大组合数取mod lucas 定理
    多校4
    多校2
    2016多校1
    百度之星 初赛B续
    iot-web增加apis-namespace组件
    25.75k8s
    新项目增加gradlew
    vue图片点击放大预览v-viewer
  • 原文地址:https://www.cnblogs.com/wangyurzee7/p/5215181.html
Copyright © 2020-2023  润新知