Luogu P3567 [POI2014] KUR-Couriers (chairman tree + two points on the tree)

Topic link

General idea

image.png

Problem-solving ideas

A simpler chair tree question.
Each time you inquire, first deal with the current interval, and then divide the
current two partitions on the chair tree as [l, r] [l, r][l,r ] , and the minimum number of occurrences to meet the requirements iskkk k = ⌊ r − l + 1 2 ⌋ + 1 k=\lfloor \frac{r-l+1}{2} \rfloor +1 k=2rl+1+1)。

  • If [l, r] [l, r][l,r ] The values ​​of the left and right halves are both less thankkk : Exit directly and output0 00
  • Otherwise, there must be and only half of the left and right halves have a value greater than or equal to kkk : Find that half and continue to divide
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int Maxn=500000+10,Maxm=11000000+10;
int sum[Maxm],ls[Maxm],rs[Maxm];
int a[Maxn],root[Maxn];
int n,m,idcnt;
inline int read()
{
    
    
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
    
    if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return s*w;
}
void modify(int &x,int y,int l,int r,int pos)
{
    
    
	x=++idcnt;
	ls[x]=ls[y];
	rs[x]=rs[y];
	sum[x]=sum[y]+1;
	if(l==r)return;
	int mid=(l+r)>>1;
	if(pos<=mid)modify(ls[x],ls[y],l,mid,pos);
	else modify(rs[x],rs[y],mid+1,r,pos);
}
int query(int x,int y,int l,int r,int v)
{
    
    
	if(sum[x]-sum[y]<v)return 0;
	if(l==r)return l;
	int mid=(l+r)>>1,ret=0;
	ret=query(ls[x],ls[y],l,mid,v);
	ret=max(ret,query(rs[x],rs[y],mid+1,r,v));
	return ret;
}
int main()
{
    
    
//	freopen("in.txt","r",stdin);
	n=read(),m=read();
	for(int i=1;i<=n;++i)
	a[i]=read();
	for(int i=1;i<=n;++i)
	modify(root[i],root[i-1],1,n,a[i]);
	while(m--)
	{
    
    
		int x=read(),y=read();
		int ans=query(root[y],root[x-1],1,n,((y-x+1)>>1)+1);
		printf("%d\n",ans);
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/Brian_Pan_/article/details/106920404