woj2443 L的鞋子

题面

L是壕,他非常喜欢鞋子,他专门在他的别墅中修建了一个鞋柜,鞋柜是呈线性的,为了好找鞋子,他把他的鞋子分成了c种。虽然L没有小学毕业,但是对数字非常偏爱,他很忌讳奇数,因为他觉得不吉利(壕都是这样的)。他想知道对于一个区间[l,r]中,有多少种鞋子恰好出现正偶数次。

输入

第一行3个整数,n,c,m 第二行n个数,每个数Ai在[1,c],表示第i双鞋子的样式 接下来m行,每行2个整数l,r,表示询问[l,r]的答案

输出

m行,回答答案 样例输入

5 5 3
1 1 2 2 3
1 5
3 4
2 3

样例输出

2
1
0

提示 共有10组测试数据 1-4组n,m=500,2000,5000,10000,c=1000 5-7组n,m=20000,30000,40000,c=10000 8-10组n,m=50000,80000,100000,c=100000 数据保证随机生成

解答

莫队裸题。注意一下区间左右移动。

# include <cstdio>
# include <algorithm>
# include <stdio.h>
# include <vector>
# include <iostream>
using namespace std;
const int MAXM = 100010;
const int MAXN = 100010;
int block_len;
struct Q{int l,r,id;bool operator<(const Q&q1){int x = (l-1)/block_len+1;int y = (q1.l-1)/block_len+1;return x==y?r<q1.r:x<y; }} querys[MAXM];
int top;
int a[MAXN],cnt[MAXN],ans;
int anss[MAXM];
void add(int pos){
    cnt[a[pos]]++;
    if(cnt[a[pos]]%2==0)ans++;
    else if(cnt[a[pos]]%2==1&&cnt[a[pos]]!=1)ans--;
}
void del(int pos){
    cnt[a[pos]]--;
    if(cnt[a[pos]]%2==0&&cnt[a[pos]]!=0)ans++;
    else if(cnt[a[pos]]%2==1)ans--;
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    int n,c,m;cin>>n>>c>>m;
    int l = 0,r = 0;
    for(int i = 1;i<=n;i++){
        cin>>c;a[i] = c;
    }
    block_len = sqrt(n);
    for(int i = 1;i<=m;i++){
        cin>>l>>r;
        querys[++top].l = l,querys[top].r = r,querys[top].id = i;
    }
    sort(querys+1,querys+1+top);
    l = 1,r = 1;cnt[a[1]]++;
    for(int i = 1;i<=m;i++){
        while(l>querys[i].l)add(--l);
        while(r<querys[i].r)add(++r);
        while(l<querys[i].l)del(l++);
        while(r>querys[i].r)del(r--);
        anss[querys[i].id] = ans;
    }
    for(int i = 1;i<=m;i++)cout<<anss[i]<<endl;
    return 0;
}