其他分享
首页 > 其他分享> > [国家集训队]middle

[国家集训队]middle

作者:互联网

序列 \(a_{1...n}\) 的中位数定义为排好序后 \(a_{\lceil\frac n2\rceil}\)。给你 \(q\) 次询问(强制在线),询问 \(l\in [a,b],r\in[c,d]\) 的所有 \(a_{[l,r]}\) 的中位数最大值。n,q<=3e5

Hint

  1. 区间+中位数 ===========> 二分答案+把>=mid的设1,<mid的设-1
  2. 最大中位数:区间和最大,sum[b+1,c-1]+后缀最大值[a,b]+前缀最大值[c,d]
  3. 考虑check,先离散化a,预处理出每个mid=1...n的可供查询区间sum,maxsufsum,maxpresum的数据结构,由于每次只改动分界处的值对应的一些下标,总共改动O(n)次,所以用主席树。
#include <bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
inline int read(){
	register char ch=getchar();register int x=0;
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
const int N=2e4+5;
int n,q,tot,a[N],arr[N],rt[N],x[4];
vector<int>b[N];
struct node {
	int s,s1,s2,ls,rs;
}t[N<<5];
void pushup(int k){
	t[k].s=t[t[k].ls].s+t[t[k].rs].s;
	t[k].s1=max(t[t[k].ls].s1,t[t[k].ls].s+t[t[k].rs].s1);
	t[k].s2=max(t[t[k].rs].s2,t[t[k].rs].s+t[t[k].ls].s2);
}
void build(int l,int r,int &k){
	if(!k)k=++tot;
	if(l==r){t[k].s=t[k].s1=t[k].s2=1;return;}
	int mid=l+r>>1;
	build(l,mid,t[k].ls),build(mid+1,r,t[k].rs);
	pushup(k);
}
void chg(int p,int l,int r,int &k,int ok){
	k=++tot,t[k]=t[ok];
	if(l==r){t[k].s=t[k].s1=t[k].s2=-1;return;}
	int mid=l+r>>1;
	if(p<=mid)chg(p,l,mid,t[k].ls,t[ok].ls);
	else chg(p,mid+1,r,t[k].rs,t[ok].rs);
	pushup(k);
}
int ask(int L,int R,int l,int r,int k){
	if(L<=l&&r<=R)return t[k].s;
	int mid=l+r>>1,s=0;
	if(L<=mid)s+=ask(L,R,l,mid,t[k].ls);
	if(R>mid)s+=ask(L,R,mid+1,r,t[k].rs);
	return s;
}
int ask1(int L,int R,int l,int r,int k){
	if(L<=l&&r<=R)return t[k].s1;
	int mid=l+r>>1,s=0;
	if(L<=mid)s=ask1(L,R,l,mid,t[k].ls);
	if(R>mid&&L>mid)s=ask1(L,R,mid+1,r,t[k].rs);
	if(L<=mid&&R>mid)s=max(s,ask(L,R,l,mid,t[k].ls)+ask1(L,R,mid+1,r,t[k].rs));
//	cout<<L<<' '<<R<<' '<<l<<' '<<r<<' '<<t[k].s<<' '<<s<<'\n';
	return s;
}
int ask2(int L,int R,int l,int r,int k){
	if(L<=l&&r<=R)return t[k].s2;
	int mid=l+r>>1,s=0;
	if(R>mid)s=ask2(L,R,mid+1,r,t[k].rs);
	if(R<=mid&&L<=mid)s=ask2(L,R,l,mid,t[k].ls);
	if(L<=mid&&R>mid)s=max(s,ask(L,R,mid+1,r,t[k].rs)+ask2(L,R,l,mid,t[k].ls));
	return s;
}
int main(){
	n=read();
	for(int i=1;i<=n;i++)a[i]=read(),arr[i]=a[i];
	sort(arr+1,arr+n+1);
	int u=unique(arr+1,arr+n+1)-arr-1;
	unordered_map<int,int>mp;
	for(int i=1;i<=u;i++)mp[arr[i]]=i;
	for(int i=1;i<=n;i++)a[i]=mp[a[i]],b[a[i]].push_back(i);
	rt[1]=++tot;
	build(1,n,rt[1]);
	for(int i=2;i<=u;i++){
		rt[i]=++tot;int las=rt[i-1];
		for(int j:b[i-1])chg(j,1,n,rt[i],las),las=rt[i];
	//	puts("o");cout<<ask1(2,4,1,n,rt[i])<<' ';puts("oo");
	}
	q=read();
	for(int o=0;q--;){
		for(int i=0;i<4;i++)x[i]=(read()+o)%n+1;
		sort(x,x+4);
		int L=0,R=u+1,mid;
		while(L<R-1){
			mid=L+R>>1;//cout<<mid<<":\n";
			if(ask1(x[2],x[3],1,n,rt[mid])+ask2(x[0],x[1],1,n,rt[mid])+(x[2]-x[1]<=1?0:ask(x[1]+1,x[2]-1,1,n,rt[mid]))>=0)L=mid;
			else R=mid;
		}
		cout<<arr[L]<<'\n',o=arr[L];
	}
}

标签:ch,rs,int,mid,中位数,middle,ls,国家集训队
来源: https://www.cnblogs.com/impyl/p/16343455.html