[National Training Team]middle——Median Thinking Question

Portal

P2839 [National Training Team]middle

answer

When it comes to finding the median, the general routine method is to divide the answer, and then find the rank of the number in the interval.

But this question a little bit different, interval uncertain size, so we use a more universal solution to the problem median routine method,

Suppose the number of <mid is -1, and the number of ≥mid is 1 to obtain the b array, then if the sum of the interval S≥0, then the median of the interval ≥mid, if S<0, then the median of the interval <mid;

For l\epsilon [a,b],r\epsilon [c,d]the interval, first [b+1,c-1]the value in the interval must be added, and then, to maximize the median, that is to make S as large as possible,

So add [a,b]the largest suffix in and [c,d]the largest prefix in, and then determine whether S is positive or negative;

The interval sum and maximum prefix suffix can be maintained by the line segment tree, which is simple;

So how to find the b array? After discretizing the a array, there are no more than n mids in total, and there is a different b array for each mid.

Build n line segment trees? Time and space cannot pass;

Considering from b(mid)to b(mid+1), it can be found that only the number whose rank is mid will change from 1 to -1, so the chairman tree can be used to find each tree. The complexityO (nlogn)

Query single-time complexity O(log^2n), so total complexity O (nlog ^ 2n).

There is no need to write 3 kinds of line segment trees, because the interval sum is used when maintaining the maximum prefix suffix in the line segment tree, so you can use a line segment tree to maintain three values ​​for easy calling;

The query function does not need to write 3 separately, only one function returns 3 values, the complexity is the same, and the constant requirement of this question is not harsh (5625000*constant), the constant is a little bigger and you can just pass it.

Code

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define MAXN 20005
using namespace std;
inline ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
	return f?x:-x;
}
int n,q,IN,root[MAXN],in[5],id;
ll a[MAXN],b[MAXN],ans;
vector<int>c[MAXN];
struct itn{
	int ls,rs,s,pr,su;
	itn(){}
	itn(int L,int R,int S,int P,int U){
		ls=L,rs=R,s=S,pr=P,su=U;
	}
}t[MAXN*20];
map<ll,int>mp;
inline void build(int x,int l,int r){
	if(l==r){t[x].s=t[x].pr=t[x].su=1;return;}
	int mid=(l+r)>>1;
	t[x].ls=++IN,t[x].rs=++IN;
	build(t[x].ls,l,mid),build(t[x].rs,mid+1,r);
	t[x].s=t[t[x].ls].s+t[t[x].rs].s;
	t[x].pr=max(t[t[x].ls].pr,t[t[x].ls].s+t[t[x].rs].pr);
	t[x].su=max(t[t[x].rs].su,t[t[x].rs].s+t[t[x].ls].su);
}
inline void add(int x,int y,int l,int r,int a){
	if(l==r){t[x].s=t[x].pr=t[x].su=-1;return;}
	int mid=(l+r)>>1;
	if(a<=mid)t[x].ls=++IN,t[x].rs=t[y].rs,add(t[x].ls,t[y].ls,l,mid,a);
	else t[x].ls=t[y].ls,t[x].rs=++IN,add(t[x].rs,t[y].rs,mid+1,r,a);
	t[x].s=t[t[x].ls].s+t[t[x].rs].s;
	t[x].pr=max(t[t[x].ls].pr,t[t[x].ls].s+t[t[x].rs].pr);
	t[x].su=max(t[t[x].rs].su,t[t[x].rs].s+t[t[x].ls].su);
}
inline itn query(int x,int l,int r,int a,int b){
	if(a>b)return itn(a,b,0,0,0);
	if(l==a&&r==b)return itn(a,b,t[x].s,t[x].pr,t[x].su);
	int mid=(l+r)>>1;
	if(a<=mid){
		if(b>mid){
			itn u=query(t[x].ls,l,mid,a,mid),v=query(t[x].rs,mid+1,r,mid+1,b);
			return itn(a,b,u.s+v.s,max(u.pr,u.s+v.pr),max(v.su,v.s+u.su));
		}
		else return query(t[x].ls,l,mid,a,b);
	}
	else return query(t[x].rs,mid+1,r,a,b);
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)a[i]=read(),mp[a[i]];
	map<ll,int>::iterator it;
	for(it=mp.begin();it!=mp.end();it++)b[++id]=it->first,it->second=id;
	for(int i=1;i<=n;i++)a[i]=mp[a[i]],c[a[i]].push_back(i);
	root[1]=++IN,build(IN,1,n);
	for(int i=2;i<=id;i++){
		root[i]=root[i-1];
		for(int j=0;j<c[i-1].size();j++){
			int x=++IN;
			add(x,root[i],1,n,c[i-1][j]),root[i]=x;
		}
	}
	q=read();
	while(q--){
		for(int i=0;i<4;i++)in[i]=(read()+ans)%(1ll*n)+1;
		sort(in,in+4);
		int l=1;
		for(int i=15;i>=0;i--)
			if(l+(1<<i)<=id){
				int o=l+(1<<i),sum=query(root[o],1,n,in[1]+1,in[2]-1).s;
				sum+=query(root[o],1,n,in[0],in[1]).su+query(root[o],1,n,in[2],in[3]).pr;
				if(sum>-1)l=o;
			}
		printf("%lld\n",ans=b[l]);
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43960287/article/details/111887553