卧薪尝胆,厚积薄发。
作诗
Date: Thu Jul 12 18:07:39 CST 2018 In Category: NoCategory

Description:

$N$ 个数, $M$ 组询问,每次问 $[l,r]$ 中有多少个数出现正偶数次。强制在线。
$1\le n \le 10^5$

Solution:

分块,维护从第 $i$ 个块开头到结尾数字 $j$ 的出现次数 $cnt[i][j]$ 和块 $i$ 到 $j$ 的答案 $f[i][j]$ ,开个桶扫一遍增减答案就好,对于询问同样暴力处理两边零散的部分即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<stack>
#include<cstring>
using namespace std;
int n,c,m;
#define MAXN 100001
int a[MAXN];
int siz,tot,L[320],R[320],belong[MAXN];
void build(int l,int r,int k)
{
L[k] = l;R[k] = r;
for(int i = l;i <= r;++i)
belong[i] = k;
return;
}
int cnt[320][MAXN],f[320][320];
int num[MAXN];
stack<int> s;
int read()
{
int res = 0;
char c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res;
}
int main()
{
scanf("%d%d%d",&n,&c,&m);
for(int i = 1;i <= n;++i)
a[i] = read();
tot = siz = sqrt(n);
for(int i = 1;i <= tot;++i)
build((i - 1) * siz + 1,i * siz,i);
if(siz * siz < n){build(R[tot] + 1,n,tot + 1);++tot;}
memset(cnt,0,sizeof(cnt));
for(int i = 1;i <= tot;++i)
{
int res = 0;
for(int j = i;j <= tot;++j)
{
for(int k = L[j];k <= R[j];++k)
{
if(cnt[i][a[k]] % 2 == 1)++res;
else if(cnt[i][a[k]] != 0)--res;
++cnt[i][a[k]];
}
f[i][j] = res;
}
}
int l,r;
int lastans = 0;
for(int i = 1;i <= m;++i)
{
l = read();r = read();
l = (l + lastans) % n + 1;
r = (r + lastans) % n + 1;
if(l > r)swap(l,r);
int ans = 0;
if(belong[l] == belong[r])
{
for(int k = l;k <= r;++k)
{
if(num[a[k]] % 2 == 1)++ans;
else if(num[a[k]] != 0)--ans;
++num[a[k]];
s.push(a[k]);
}
printf("%d\n",lastans = ans);
while(!s.empty())
{
--num[s.top()];
s.pop();
}
continue;
}
ans = f[belong[l] + 1][belong[r] - 1];
for(int k = l;k <= R[belong[l]];++k)
{
if((num[a[k]] + cnt[belong[l] + 1][a[k]] - cnt[belong[r]][a[k]]) % 2 == 1)++ans;
else if(num[a[k]] + cnt[belong[l] + 1][a[k]] - cnt[belong[r]][a[k]] != 0)--ans;
++num[a[k]];
s.push(a[k]);
}
for(int k = L[belong[r]];k <= r;++k)
{
if((num[a[k]] + cnt[belong[l] + 1][a[k]] - cnt[belong[r]][a[k]]) % 2 == 1)++ans;
else if(num[a[k]] + cnt[belong[l] + 1][a[k]] - cnt[belong[r]][a[k]] != 0)--ans;
++num[a[k]];
s.push(a[k]);
}
printf("%d\n",lastans = ans);
while(!s.empty())
{
--num[s.top()];
s.pop();
}
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡