题解 P3709 【大爷的字符串题】

Link

P3709 大爷的字符串题

Solve

通过观察我们发现,对于一列数,rp减小值就是众数的个数,由于可以离线,我们就可以用莫队来解决这个问题,每次几下cntx,retx有点难理解,加入一个数的时候,用Ans刷cnt的max,删除一个数时,判断这个数是不是众数,如果只有有且只有一个删除的cnt而且删除的是当前的众数是,我们把Ans--,因为如果ret[cnt[x]-1]肯定不为0,可能是当前是这个数,也可能有好多个众数,剩下的就是莫队了。

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=200005;
int n,m,cnt[maxn],a[maxn],block[maxn],ans[maxn],len,tot,now,ret[maxn];
struct AS{
	int x,id;
	bool operator <(const AS B)const {return x<B.x;}
}c[maxn];
struct BS{
	int l,r,id;
	bool operator <(const BS B)const {return block[l]^block[B.l]?block[l]<block[B.l]:(block[l]&1)?r<B.r:r>B.r;}
}q[maxn];
inline int read(){
	int ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
	return ret*f;
}
void inc(int x){
	ret[cnt[x]]--;
	ret[++cnt[x]]++;
	now=max(now,cnt[x]);
}
void del(int x){
	ret[cnt[x]]--;
	if(ret[cnt[x]]==0&&cnt[x]==now)now--;
	cnt[x]--;
	ret[cnt[x]]++;
}
int main(){
	freopen("P3709.in","r",stdin);
	freopen("P3709.out","w",stdout);
	n=read();m=read();len=sqrt(n);
	for(int i=1;i<=n;i++)c[i].x=read(),c[i].id=i,block[i]=(i-1)/len+1;
	sort(c+1,c+1+n);
	a[c[1].id]=++tot;
	for(int i=2;i<=n;i++){
		if(c[i].x!=c[i-1].x)tot++;
		a[c[i].id]=tot;
	}
	for(int i=1;i<=m;i++)q[i].l=read(),q[i].r=read(),q[i].id=i;
	sort(q+1,q+1+m);
	int L=1,R=0;
	for(int i=1;i<=m;i++){
		while(L<q[i].l)del(a[L++]);
		while(L>q[i].l)inc(a[--L]);
		while(R<q[i].r)inc(a[++R]);
		while(R>q[i].r)del(a[R--]);
		ans[q[i].id]=now;
	}
	for(int i=1;i<=m;i++)printf("%d
",-ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/martian148/p/13545145.html