洛谷P7252 棒棒糖

题目描述

Coffee 的世界里也是有棒棒糖卖的,Coffee 买了 nn 只连着的棒棒糖。这 nn 只棒棒糖包裹在小塑料袋中,排成 一列,相邻的两只棒棒糖的塑料袋是接起来的。为了方便,我们把棒棒糖从左到右编号为1\cdots n1⋯n。

每只棒棒糖有一种口味。第 ii 只的口味是 c_ici​。两只棒棒糖 i,ji,j 的口味相同,当且仅当 c_i=c_jci​=cj​。Coffee 对 mm 只棒棒糖总体口味的评价比较奇怪。如果这 mm 只棒棒糖中,有一种口味 c_0c0​ 的数量严格大于总数的一半,那么 Coffee 认为这 mm 只棒棒糖主要是 c_0c0​ 口味的。Coffee 知道,这里的 c_0c0​ 如果存在就一定是唯一的。而当 c_0c0​ 不存在时,Coffee 认为这 mm 只棒棒糖是混合口味的。

Coffee 暂时舍不得吃棒棒糖,它在想一些好玩的问题。如果考虑棒棒糖序列的一个连续子序列 s\cdots t(1\leq s\leq t\leq n)s⋯t(1≤s≤t≤n),包括棒棒糖 ss 和 tt。那么这 t-s+1t−s+1 只棒棒糖的总体口味是什么呢?

Coffee有一堆这样的问题,一共 mm 个。第 ii 个问题是棒棒糖子序列 s_i\cdots t_isi​⋯ti​ 的总体口味,请你帮忙解决。

输入格式

第一行两个用空格隔开的整数,分别表示 n,mn,m。

接下来 nn 行,每行一个整数,表示 c_ici​。

接下来 mm 行,每行两个整数,表示 s_i,t_isi​,ti​。

输出格式

mm 行,每行一个整数,表示每个询问的总体口味。如果总体口味为混合口味则输出 00。

输入输出样例

输入 #1复制

5 3 
1 
2 
2
1
1
1 5
2 5
2 4

输出 #1复制

1
0
2

说明/提示

样例解释 1

在第一个询问中,口味 11 出现 33 次,大于总数的一半,所以总体口味为 11。

在第二个询问中,没有一种口味出现次数大于总数的一半,所以为混合口味。

在第三个询问中,口味 22 出现 22 次,大于总数的一半,所以总体口味为 22。

数据范围

对于 100\%100% 的数据,1\leq n,m,c_i\leq 5\times 10^41≤n,m,ci​≤5×104。

上代码:

#include<bits/stdc++.h>
using namespace std;
#define N 50005
int n,m,a[N],b[N],c[N],len,an[N],ans,ll=1,rr,maxn;
struct question{
	int l,r,id;
}que[N];
inline int read(){
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}//快读 
inline bool cmp(question x,question y){
	if(x.l/len==y.l/len)return ((x.l/len)&1)?x.r<y.r:x.r>y.r;
	return x.l<y.l;
}//比较函数 
multiset<int>s[N];
inline void add(int x){
	s[b[a[x]]].erase(a[x]);
	--c[b[a[x]]],++b[a[x]];
	s[b[a[x]]].insert(a[x]);
	++c[b[a[x]]];
	if(b[a[x]]>maxn)++maxn;//如果超过了最大值就更新最大值 
}
inline void del(int x){
	s[b[a[x]]].erase(a[x]);
	--c[b[a[x]]],--b[a[x]];
	s[b[a[x]]].insert(a[x]);
	++c[b[a[x]]];
	if(b[a[x]]+1==maxn)maxn-=(c[b[a[x]]+1]==0);//如果最大值消失,就--(因为此时b[a[x]]为最大值)
}
int main(){
	n=read(),m=read(),len=sqrt(n);
	for(int i=1;i<=n;++i)a[i]=read();
	for(int i=1;i<=m;++i)que[i].l=read(),que[i].r=read(),que[i].id=i;
	sort(que+1,que+m+1,cmp);
	for(int i=1;i<=n;++i)s[0].insert(a[i]),++c[0];//注意一定在开始时要加入,否则会RE 
	for(int i=1;i<=m;++i){
		while(ll>que[i].l)add(--ll);
		while(rr<que[i].r)add(++rr);
		while(ll<que[i].l)del(ll++);
		while(rr>que[i].r)del(rr--);//莫队正常操作 
		an[que[i].id]=(maxn>((que[i].r-que[i].l+1)/2))?(s[maxn].empty()?0:*s[maxn].begin()):0;//判断是否有解 
	}
	for(int i=1;i<=m;++i)printf("%d\n",an[i]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值