题解:P7764 [COCI 2016/2017 #5] Poklon

题面

思路

维护区间贡献,能 \(O(1)\) 转移,数据 \(5 \times 10^5\),容易想到用莫队实现,还不用离散化。

不过在这进食一下后人:不要用 map 记录,直接用桶数组就好了,map 常数太大很容易被卡。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
inline int read(){
	int s=0,f=1;char t=getchar();
	while('0'>t||t>'9'){
		if(t=='-')f=-1;
		t=getchar();
	}
	while('0'<=t&&t<='9'){
		s=(s<<1)+(s<<3)+t-'0';
		t=getchar();
	}
	return s*f;
}
int n,m;
int B;
int a[N],res[N],block[N],mp[N];
int ans;
struct node{
	int l,r,id;
}q[N];
inline bool cmp(node x,node y){
	if(block[x.l]==block[y.l]){
		if((block[x.l]&1)==1) return x.r>y.r;
		return x.r<y.r;
	}
	return x.l<y.l;
}
inline void upd(int x,int d){
	if(mp[a[x]]==2) ans--;
	mp[a[x]]+=d;
	if(mp[a[x]]==2) ans++;
}
int main(){
	n=read();m=read();
	B=sqrt(n);
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	for(int i=1;i<=m;i++){
		q[i].l=read();q[i].r=read();
		q[i].id=i;
		block[i]=(i-1)/B+1;
	}
	sort(q+1,q+m+1,cmp);
	int l=1,r=0;
	for(int i=1;i<=m;i++){
		while(q[i].l<l) upd(--l,1);
		while(r<q[i].r) upd(++r,1);
		while(l<q[i].l) upd(l++,-1);
		while(q[i].r<r) upd(r--,-1);
		res[q[i].id]=ans;
	}
	for(int i=1;i<=m;i++) printf("%lld\n",res[i]);
	return 0;
}
posted @ 2025-08-30 17:41  幻琳  阅读(9)  评论(0)    收藏  举报