不会莫队+在线只能用分块
卡常卡了一个小时 草 整个人都不好了
自己YY出来的 记录a[i][j]表示i在块j中出现的次数。
对于这个东西求出前缀和ss方便后面使用。
再记录sum[i][j]表示块[i,j]中满足条件的个数,这玩意可以预处理出来。
然后对于询问(x,y),枚举左右多出来的那一截里面的数带来的贡献(有可能为负),加上中间的sum即可。
注意特判,以及对于50000以上的数据直接分sqrt个是会MLE的,要特殊处理。
然后卡常的话:register+dzyoの快读+手动memset才过 MMP
#include<bits/stdc++.h>
#define re register
const int N=100005;
const int K=220;
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int read() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
inline void write(int x)
{
if(x<0)
{
x=-x;
putchar('-');
}
if(x>9) write(x/10);
putchar((x%10)+'0');
}
int n,c,m,num,k,a[N][K+5],v[N],b[N],ss[N][K+5],sum[K+5][K+5]; //sum:第i个块到第j个块中有多少合法答案
int l[K],r[K],temp[N],op[N];
bool vis[N];
inline void Solve(int st) //从第l个块往后处理sum
{
memset(temp,0,sizeof(temp));
int k=0;
for(re int ed=st;ed<=num;ed++)
{
for(re int i=l[ed];i<=r[ed];i++)
{
if(temp[v[i]]&1) k++;
else if(temp[v[i]]) k--;
temp[v[i]]++;
}
sum[st][ed]=k;
}
}
vector <int> vec;
inline int query(int x,int y)
{
if(b[x]==b[y])
{
int ans=0;
for(int i=x;i<=y;i++) vis[v[i]]=0,op[v[i]]=0;
for(int i=x;i<=y;i++) op[v[i]]++;
for(int i=x;i<=y;i++)
{
if(vis[v[i]]) continue;
vis[v[i]]=1;
if(!(op[v[i]]&1)) ans++;
}
return ans;
}
else
{
vec.clear();
int ans=0;
int st=b[x]+1,ed=b[y]-1;
for(re int i=x;i<=min(b[x]*k,y);i++) op[v[i]]=0,vis[v[i]]=0;
for(re int i=(b[y]-1)*k+1;i<=y;i++) op[v[i]]=0,vis[v[i]]=0;
for(re int i=x;i<=min(b[x]*k,y);i++) vec.push_back(v[i]),op[v[i]]++;
for(re int i=(b[y]-1)*k+1;i<=y;i++) vec.push_back(v[i]),op[v[i]]++;
for(re int i=0;i<vec.size();i++)
{
if(vis[vec[i]]) continue;
vis[vec[i]]=1;
int cnt=op[vec[i]];
int tmp=ss[vec[i]][ed]-ss[vec[i]][st-1];
if(!tmp)
{
if(!(cnt&1)) ans++;
continue;
}
if(tmp&1&&cnt&1) ans++;
if(!(tmp&1)&&cnt&1) ans--;
}
return ans+sum[st][ed];
}
}
int main()
{
n=read(),c=read(),m=read();
k=sqrt(n); num=n/k;
if(n>=50000) num=K,k=n/num;
if(n%k!=0) num++;
for(re int i=1;i<=n;i++)
{
v[i]=read();
b[i]=(i-1)/k+1;
a[v[i]][b[i]]++;
}
for(re int i=1;i<=c;i++)
for(re int j=1;j<=num;j++)
ss[i][j]=ss[i][j-1]+a[i][j];
for(re int i=1;i<=num;i++) l[i]=(i-1)*k+1,r[i]=l[i]+k-1;
r[num]=n;
for(re int i=1;i<=num;i++) Solve(i);
int x,y;
for(re int i=1;i<=m;i++)
{
x=read(),y=read();
write(query(x,y)),putchar('\n');
}
return 0;
}