题解: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;
}

浙公网安备 33010602011771号