• P2839 [国家集训队]middle


    链接

    考虑区间的中位数为 (v) 应该满足什么条件。

    让该区间中小于 (v) 的值等于 (-1),大于等于 (v) 的值等于 (1),若和大于等于 (0),则该区间的中位数大于等于 (v),否则小于 (v)

    (注意数的个数为偶数时,则取偏大的值作为中位数

    所以我们可以二分答案,以权值为根,下标为叶子按上述方式储存前缀和建一棵主席树。

    具体的,在根为 (rt_i) 的树中,序列里小于等于第 (i) 小值的为 (-1),大于的为 (1),储存其前缀和的最大值和最小值。

    所以我们要维护的操作为区间最大值,区间最小值,区间修改,用标记永久化实现。

    (code)(洛谷 (rk1)

    #include<bits/stdc++.h>
    #define IL inline
    #define LL long long
    #define pb push_back
    using namespace std;
    const int N=2e4+3,inf=0x3f3f3f3f;
    int n,m,num,cnt,ls[N*400],rs[N*400],Max[N*400],Min[N*400],add[N*400],rt[N];
    int a[N],b[N],q[5],ans;
    vector<int>p[N];
    IL int in(){
      char c;int f=1;
      while((c=getchar())<'0'||c>'9')
        if(c=='-') f=-1;
      int x=c-'0';
      while((c=getchar())>='0'&&c<='9')
        x=x*10+c-'0';
      return x*f;
    }
    void build(int &o,int l,int r){
      o=++cnt,Max[o]=r,Min[o]=l;
      if(l==r) return;
      int mid=l+r>>1;
      build(ls[o],l,mid),build(rs[o],mid+1,r);
    }
    void mdy(int &o,int p,int l,int r,int ll,int rr){
      o=++cnt,ls[o]=ls[p],rs[o]=rs[p],add[o]=add[p];
      if(l>=ll&&r<=rr){add[o]=add[p]-2,Max[o]=Max[p]-2,Min[o]=Min[p]-2;return;}
      int mid=l+r>>1;
      if(ll<=mid) mdy(ls[o],ls[p],l,mid,ll,rr);
      if(rr>mid) mdy(rs[o],rs[p],mid+1,r,ll,rr);
      Max[o]=max(Max[ls[o]],Max[rs[o]])+add[o],
      Min[o]=min(Min[ls[o]],Min[rs[o]])+add[o];
    }
    int query_Max(int o,int l,int r,int ll,int rr){
    	if(l>=ll&&r<=rr) return Max[o];
    	int mid=l+r>>1,res=-inf;
    	if(ll<=mid) res=max(res,query_Max(ls[o],l,mid,ll,rr)+add[o]);
    	if(rr>mid) res=max(res,query_Max(rs[o],mid+1,r,ll,rr)+add[o]);
    	return res;
    }
    int query_Min(int o,int l,int r,int ll,int rr){
    	if(l>=ll&&r<=rr) return Min[o];
    	int mid=l+r>>1,res=inf;
    	if(ll<=mid) res=min(res,query_Min(ls[o],l,mid,ll,rr)+add[o]);
    	if(rr>mid) res=min(res,query_Min(rs[o],mid+1,r,ll,rr)+add[o]);
    	return res;
    }
    void solve(){
      for(int i=1;i<=4;++i) q[i]=(in()+ans)%n+1;sort(q+1,q+5);
    	int l=1,r=num;
    	while(l<r){
    	  int mid=l+r+1>>1;
    	  int qr=query_Max(rt[mid-1],1,n,q[3],q[4]),ql;
    	  if(q[1]^1) ql=query_Min(rt[mid-1],1,n,q[1]-1,q[2]-1);
    	  else ql=min(0,query_Min(rt[mid-1],1,n,q[1],q[2]-1));
    	  if(qr-ql>=0) l=mid;else r=mid-1;
    	}
    	printf("%d
    ",ans=b[l]);
    }
    int main()
    {
    	n=in();Min[0]=inf,Max[0]=-inf;
    	for(int i=1;i<=n;++i) a[i]=b[i]=in();
    	sort(b+1,b+n+1),num=unique(b+1,b+n+1)-b-1;
    	for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+num+1,a[i])-b,p[a[i]].pb(i);
    	build(rt[0],1,n);
    	for(int i=1;i<=num;++i)
    	  for(int j=0;j<p[i].size();++j)
    	    if(!j) mdy(rt[i],rt[i-1],1,n,p[i][j],n);
    	    else mdy(rt[i],rt[i],1,n,p[i][j],n);
    	m=in();
    	while(m--) solve();
      return 0;
    }
    
    
  • 相关阅读:
    a 超链接标签
    select(下拉标签和textarea(文本框)
    input标签
    input 标签
    div 标签
    body 标签
    STL__网上资料
    STL_iterator返回值
    STL_算法_中使用的函数对象
    STL_std::iterator
  • 原文地址:https://www.cnblogs.com/yiqiAtiya/p/13990756.html
Copyright © 2020-2023  润新知