bzoj 2821 分类: bzoj 2015-08-07 18:38 11人阅读 评论(0) 收藏
因为强制在线,所以无法用莫队算法。。。
将序列分块,设块的大小为
首先预处理出第
然后对于每个询问,我们对整块以外的数重新计算对答案的贡献即可。
时间复杂度
根据基本不等式,每块的大小为
时间复杂度:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <iostream>
#include <algorithm>
template<class Num>void read(Num &x)
{
char c; int flag = 1;
while((c = getchar()) < '0' || c > '9')
if(c == '-') flag *= -1;
x = c - '0';
while((c = getchar()) >= '0' && c <= '9')
x = (x<<3) + (x<<1) + (c-'0');
x *= flag;
return;
}
template<class Num>void write(Num x)
{
if(x < 0) putchar('-'), x = -x;
static char s[20];int sl = 0;
while(x) s[sl++] = x%10 + '0',x /= 10;
if(!sl) {putchar('0');return;}
while(sl) putchar(s[--sl]);
}
const int maxn = 1e5+5, maxc = maxn, maxm = maxn;
const int maxs = 1308;
const double eps = 1e-5;
#define clear(__arr) memset(__arr, 0, sizeof(__arr))
#define Check(x) ((x && !(x&1))?1:0)
int n, c, m, a[maxn], ans;
int block, size, block_cnt[maxs][maxs];
int cnt[maxc], odd;
int arr[maxn], len;
int cur[maxc], vec[maxn];
void init()
{
read(n), read(c), read(m);
for(int i = 1; i <= n; i++) read(a[i]);
}
void add(int t,int val)
{
odd -= Check(cnt[a[t]]);
cnt[a[t]] += val;
odd += Check(cnt[a[t]]);
}
void prework()
{
int l, r, st, ed;
block = (n != 1)?(sqrt((double)n/log(n)*log(2))+eps):1;
size = n/block + ((n%block)?1:0);
odd = 0, l = 1, r = 1, add(1, 1);
for(int i = 1; i <= size; i++)
for(int j = i; j <= size; j++)
{
st = block*(i - 1) + 1;
ed = std::min(block*j, n);
while(l > st) --l, add(l, 1);
while(r < ed) ++r, add(r, 1);
while(l < st) add(l, -1), l++;
while(r > ed) add(r, -1), r--;
block_cnt[i][j] = odd;
}
clear(cnt);
for(int i = 1; i <= n; i++) cur[a[i]]++;
for(int i = 1; i <= c; i++) cur[i] += cur[i-1];
for(int i = n; i >= 1; i--) vec[cur[a[i]]--] = i;
cur[c + 1] = n;
}
#define GetNum(fr,to,val) (std::upper_bound(vec + cur[val] + 1, vec + cur[val + 1] + 1, to) - std::lower_bound(vec + cur[val] + 1, vec + cur[val + 1] + 1, fr))
void solve()
{
int l, r, st, ed, count;
int l_block, r_block;
for(int Case = 1; Case <= m; Case ++)
{
read(l), read(r);
l = (l + ans)%n + 1;
r = (r + ans)%n + 1;
if(l > r) std::swap(l, r);
ans = 0;
l_block = (l - 1)/block + 1;
r_block = (r - 1)/block + 1;
if(r_block - l_block <= 1)
{
for(int i = l; i <= r; i++) cnt[a[i]]++, arr[++len] = a[i];
std::sort(arr + 1, arr + len + 1);
len = std::unique(arr + 1, arr + len + 1) - (arr + 1);
for(int i = 1; i <= len; i++)
ans += Check(cnt[arr[i]]), cnt[arr[i]] = 0;
len = 0;
}
else
{
st = block*l_block + 1, ed = block*(r_block - 1);
ans = block_cnt[l_block+1][r_block-1];
for(int i = l; i < st; i++) arr[++len] = a[i];
for(int i = r; i > ed; i--) arr[++len] = a[i];
std::sort(arr + 1, arr + len + 1);
len = std::unique(arr + 1, arr + len + 1) - (arr + 1);
for(int i = 1; i <= len; i++)
{
count = GetNum(st, ed, arr[i]), ans -= Check(count);
count = GetNum(l, r, arr[i]), ans += Check(count);
arr[i] = 0;
}
len = 0;
}
write(ans), puts("");
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("2821.in","r",stdin);
freopen("2821.out","w",stdout);
#endif
init(), prework(), solve();
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。