【刷题】BZOJ 3524 [Poi2014]Couriers

Description

给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。

Input

第一行两个数n,m。
第二行n个数,a[i]。
接下来m行,每行两个数l,r,表示询问[l,r]这个区间。

Output

m行,每行对应一个答案。

Sample Input

7 5
1 1 3 2 3 4 3
1 3
1 4
3 7
1 7
6 6

Sample Output

1
0
3
0
4

HINT

【数据范围】
n,m≤500000

Solution

维护数字出现次数——主席树
同样用主席树维护\(sum\)
每次查询的时候选择满足条件的往下走就行了
因为一段数列中出现次数大于一半的至多只会有一个,所以这样暴力做的复杂度是正确的

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
#define Mid ((l+r)>>1)
#define lson l,Mid
#define rson Mid+1,r
const int MAXN=500000+10;
int n,m,A[MAXN];
std::vector<int> V;
std::map<int,int> M;
struct ChairMan_Tree{
	int cnt,lc[MAXN<<5],rc[MAXN<<5],sum[MAXN<<5],root[MAXN];
	inline void init()
	{
		cnt=0;
		memset(lc,0,sizeof(lc));
		memset(rc,0,sizeof(rc));
		memset(sum,0,sizeof(sum));
	}
	inline void Build(int &rt,int l,int r)
	{
		rt=++cnt;
		sum[rt]=0;
		if(l==r)return ;
		Build(lc[rt],lson);
		Build(rc[rt],rson);
	}
	inline void Insert(int &rt,int l,int r,int last,int pos)
	{
		rt=++cnt;
		sum[rt]=sum[last]+1;
		lc[rt]=lc[last];
		rc[rt]=rc[last];
		if(l==r)return ;
		else
		{
			if(pos<=Mid)Insert(lc[rt],lson,lc[last],pos);
			else Insert(rc[rt],rson,rc[last],pos);
		}
	}
	inline int Query(int now,int last,int l,int r,int k)
	{
		if(sum[now]-sum[last]<=k)return 0;
		if(l==r)return l;
		else
		{
			if(sum[lc[now]]-sum[lc[last]]>k)return Query(lc[now],lc[last],lson,k);
			else return Query(rc[now],rc[last],rson,k);
		}
	}
};
ChairMan_Tree T;
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void discre()
{
	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());
	for(register int i=1;i<=n;++i)
	{
		int pre=A[i];
		A[i]=lower_bound(V.begin(),V.end(),A[i])-V.begin()+1;
		M[A[i]]=pre;
	}
}
int main()
{
	read(n);read(m);
	for(register int i=1;i<=n;++i)
	{
		read(A[i]);
		V.push_back(A[i]);
	}
	discre();
	T.init();
	T.Build(T.root[0],1,n);
	for(register int i=1;i<=n;++i)T.Insert(T.root[i],1,n,T.root[i-1],A[i]);
	while(m--)
	{
		int l,r;
		read(l);read(r);
		write(T.Query(T.root[r],T.root[l-1],1,n,(r-l+1)/2),'\n');
	}
	return 0;
}
posted @ 2018-03-18 10:38  HYJ_cnyali  阅读(185)  评论(0编辑  收藏  举报