题目链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=2821
权限题,附题意:
题解:
分块题,他要求在线处理区间问题,很明显是为了卡莫队这种神奇算法,首先将序列分块,按 sqrt(n) (即根号n)分块,然后预处理出一个数组 f[i][j] 表示从第 i 块到第 j 块内,满足题意的答案,还要处理出另一个数组 cnt[i][j] 表示前 i 块中数字 j 出现了多少次,(不要担心数组太大开不下,三千两百万它还真就是存下了,o.o!),这样的话当询问区间 (i,j)时,我们利用 f[i][j] 通过各种判断首先将包含在这个区间里的块的答案统计出来,再利用 cnt[i][j] 将两头或是一头没有达到一整快的部分暴力的统计,一边统计一边修改已经得到的答案即可,时限还是够的。
注意题中一个特别坑的地方,
他特别心机的的在mod与n+1 之间加了一个空格,让大家以为是mod(n+1)实际上却是(mod n)+1。。2333
代码
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
#define maxn (100005)
#define maxs (320)
using namespace std;
int vis[maxn],ans,L,R,len,n,num,c,m,sq[maxn],f[maxs][maxs],cnt[maxs][maxn],a[maxn],st[maxs],tmp[maxn];
void solve(int l,int r)//计算 l,r
{
if (sq[l]==sq[r] || sq[l]+1==sq[r])
{
for (int i=l;i<=r;i++)
{
vis[a[i]]++;
if (vis[a[i]]%2==0) ans++;
else if (vis[a[i]]!=1) ans--;
}
for (int i=l;i<=r;i++)
vis[a[i]]=0;
return ;
}
if (l==st[sq[l]] && r==st[sq[r]+1]-1)
{
ans=f[sq[l]][sq[r]];
return ;
}
else if (l==st[sq[l]])
{
ans=f[sq[l]][sq[r]-1];
for (int i=st[sq[r]];i<=r;i++)
vis[a[i]]=cnt[sq[r]-1][a[i]]-cnt[sq[l]-1][a[i]];
for (int i=st[sq[r]];i<=r;i++)
{
vis[a[i]]++;
if (vis[a[i]]%2==0) ans++;
else if (vis[a[i]]!=1) ans--;
}
for (int i=st[sq[r]];i<=r;i++)
vis[a[i]]=0;
return ;
}
else if (r==st[sq[r]+1]-1)
{
ans=f[sq[l]+1][sq[r]];
for (int i=l;i<st[sq[l]+1];i++)
vis[a[i]]=cnt[sq[r]][a[i]]-cnt[sq[l]][a[i]];
for (int i=l;i<st[sq[l]+1];i++)
{
vis[a[i]]++;
if (vis[a[i]]%2==0) ans++;
else if (vis[a[i]]!=1) ans--;
}
for (int i=l;i<st[sq[l]+1];i++)
vis[a[i]]=0;
return ;
}
else
{
int x=sq[l]+1;
int y=sq[r]-1;
ans=f[x][y];
for (int i=l;i<st[x];i++)
vis[a[i]]=cnt[y][a[i]]-cnt[x-1][a[i]];
for (int i=st[y+1];i<=r;i++)
vis[a[i]]=cnt[y][a[i]]-cnt[x-1][a[i]];
for (int i=l;i<st[x];i++)
{
vis[a[i]]++;
if (vis[a[i]]%2==0) ans++;
else if (vis[a[i]]!=1) ans--;
}
for (int i=st[y+1];i<=r;i++)
{
vis[a[i]]++;
if (vis[a[i]]%2==0) ans++;
else if (vis[a[i]]!=1) ans--;
}
for (int i=l;i<st[x];i++) vis[a[i]]=0;
for (int i=st[y+1];i<=r;i++) vis[a[i]]=0;
return ;
}
}
int main()
{
scanf("%d%d%d",&n,&c,&m);
len=sqrt(n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sq[i]=(i-1)/len+1;
cnt[sq[i]][a[i]]++;
if (sq[i]!=sq[i-1])
st[sq[i]]=i;
}
num=sq[n];
for (int i=1;i<=num;i++)
for (int j=1;j<=c;j++)
cnt[i][j]+=cnt[i-1][j];
//预处理 cnt数组
for (int i=1;i<=num;i++)
{
int tans=0;
for (int j=1;j<=c;j++)
tmp[j]=0;
for (int j=st[i];j<=n;j++)
{
tmp[a[j]]++;
if (tmp[a[j]]%2==0) tans++;
else if (tmp[a[j]]!=1) tans--;
f[i][sq[j]]=tans;
}
}//预处理 f 数组
ans=0;
for (int i=1;i<=m;i++)
{
scanf("%d%d",&L,&R);
L=(L+ans)%n+1;
R=(R+ans)%n+1;
ans=0;
if (L>R) swap(L,R);
solve(L,R);
printf("%d\n",ans);
}
}
不得不说,csdn的博客编辑最近好像十分的恶心。。。