题目大意:N个数,M组询问,每次问[l,r]中有多少个数出现正偶数次,强制在线
题解:经典分块
预处理
ans[i][j]
表示第 i 块到第 j 块的答案
sum[i][j]
表示前 j 块中元素 i 出现的次数
我的收获:2333
#include <cstdio>
#include <vector>
#include <map>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=1e9;
const int N=150005;
int n,m,blo,cnt,ans;
int pos[N],L[N],R[N];
int a[N],tmp[N];
int first[N],last[N];
int f[1505][1505];
bool mark[N];
struct data{int p,v;}b[N];
bool operator<(data a,data b){return (a.v<b.v)||(a.v==b.v&&a.p<b.p);}
void pre()
{
int tot;
for(int i=1;i<=cnt;i++)
{
for(int j=L[i];j<=n;j++) tmp[a[j]]=0;
tot=0;
for(int j=L[i];j<=n;j++)
{
if(!(tmp[a[j]]&1)&&tmp[a[j]]) tot--;
tmp[a[j]]++;
if(!(tmp[a[j]]&1)) tot++;
f[i][pos[j]]=tot;
}
}
for(int i=1;i<=n;i++) b[i].p=i,b[i].v=a[i];
sort(b+1,b+n+1);
for(int i=1;i<=n;i++)
{
if(!first[b[i].v]) first[b[i].v]=i;
last[b[i].v]=i;
}
}
int findup(int x,int v)
{
int l=first[v],r=last[v];
int tmp=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(x<b[mid].p)r=mid-1;
else {l=mid+1;tmp=mid;}
}
return tmp;
}
int finddown(int x,int v)
{
int l=first[v],r=last[v];
int tmp=INF;
while(l<=r)
{
int mid=(l+r)>>1;
if(x>b[mid].p)l=mid+1;
else {tmp=mid;r=mid-1;}
}
return tmp;
}
int find(int x,int y,int v){
return max(findup(y,v)-finddown(x,v)+1,0);
}
int query(int x,int y)
{
int ret=0,t1,t2,a1,bx=pos[x],by=pos[y];
if(bx==by||bx+1==by)
{
for(int i=x;i<=y;i++)
{
a1=a[i];if(mark[a1]) continue;
int t=find(x,y,a1);
if(!(t&1)){mark[a1]=1;ret++;}
}
for(int i=x;i<=y;i++) mark[a[i]]=0;
}
else
{
int l=L[bx+1],r=R[by-1];
ret=f[bx+1][by-1];
for(int i=x;i<l;i++)
{
a1=a[i];if(mark[a1]) continue;
t1=find(x,y,a1),t2=find(l,r,a1);
if(!(t1&1))
{if((t2&1)||!t2) ret++;}
else if(!(t2&1)&&t2) ret--;
mark[a1]=1;
}
for(int i=r+1;i<=y;i++)
{
a1=a[i];if(mark[a1]) continue;
t1=find(x,y,a1),t2=find(l,r,a1);
if(!(t1&1))
{if((t2&1)||!t2) ret++;}
else if(!(t2&1)&&t2) ret--;
mark[a1]=1;
}
for(int i=x;i<l;i++) mark[a[i]]=0;
for(int i=r+1;i<=y;i++) mark[a[i]]=0;
}
return ret;
}
void work()
{
for(int i=1;i<=m;i++)
{
int l,r;scanf("%d%d",&l,&r);
l=(l+ans)%n+1;r=(r+ans)%n+1;
if(l>r) swap(l,r);
ans=query(l,r);
printf("%d\n",ans);
}
}
void init()
{
scanf("%d%*d%d",&n,&m);blo=sqrt(n/log(n)*log(2));
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) pos[i]=(i-1)/blo+1;
cnt=pos[n];for(int i=1;i<=cnt;i++) L[i]=(i-1)*blo+1,R[i]=min(i*blo,n);
pre();
}
int main()
{
init();
work();
return 0;
}