您的位置:首页 > 其它

BZOJ 2821: 作诗(Poetize) | 分块

2018-01-02 17:55 204 查看

题目:

http://www.lydsy.com/JudgeOnline/problem.php?id=2821

 

分块.

预处理:

ans[i][j]表示i块到j块的答案;

cnt[i][j]表示i数前j块出现的次数

询问:

ret=l到r包含的整块部分答案,然后暴力处理块外的数出现次数.

我们发现关于每个数x以下情况可以影响到答案

1.x出现奇数次,整块中出现了正偶数次,ret--

2.x出现奇数次,整块中出现了奇数次,ret++

3.x出现偶数次,整块中出现了奇数次,ret++

而x在整块出现次数可以用cnt轻松的求出

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 100005
#define sq 320
using namespace std;
int cnt
[sq],sum
,n,c,m,S,s,bl
,br
,a
,ans[sq][sq],lastans, vis
;
void Init()
{
for (int i=0;i<n;i++)
if (i%S==0) br[s]=i-1,bl[++s]=i;
br[s]=n-1,bl[s+1]=br[s+1]=n;
for (int i=1;i<=s;i++)
{
for (int j=1;j<=c;j++)
cnt[j][i]=cnt[j][i-1];
for (int h=bl[i],t=br[i];h<=t;h++)
cnt[a[h]][i]=++sum[a[h]];
}
memset(sum,0,sizeof(sum));
for (int i=1;i<=s;i++)
{
int k=bl[i],tmp=0,t,c;
for (int j=k;j<n;j++) sum[a[j]]=0;
for (int j=i;j<=s;j++)
{
t=br[j];
for (;k<=t;k++)
{
if (vis[a[k]]==i)
{
c=++sum[a[k]];
if (c%2==0) tmp++;
else tmp--;
}
else vis[a[k]]=i,sum[a[k]]=1;
}
ans[i][j]=tmp;
}
}
memset(vis,0,sizeof(vis));
}
int Query(int l,int r)
{
if (r-l<2*S)
{
int tmp=0;
for (int i=l;i<=r;i++)
if (!vis[a[i]]) vis[a[i]]=1,sum[a[i]]=1;
else ++sum[a[i]];
for (int i=l;i<=r;i++)
if (vis[a[i]])
tmp+=!(sum[a[i]]%2),vis[a[i]]=0;
return tmp;
}
int L=l/S+1,R=r/S+1;
if (l==bl[L]) L--;
if (r==br[R]) R++;
int st=bl[R],ed=br[L],res=ans[L+1][R-1];
for (int i=l;i<=ed;i++)
if (!vis[a[i]]) vis[a[i]]=1,sum[a[i]]=1;
else sum[a[i]]++;
for (int i=st;i<=r;i++)
if (!vis[a[i]]) vis[a[i]]=1,sum[a[i]]=1;
else sum[a[i]]++;
for (int i=l;i<=ed;i++)
if (vis[a[i]])
{
int cnt1=sum[a[i]],cnt2=cnt[a[i]][R-1]-cnt[a[i]][L];
if (cnt2>0 && cnt2%2==0 && cnt1%2==1) res--;
if (cnt2==0 && cnt1%2==0) res++;
if (cnt2%2==1 && cnt1%2==1) res++;
sum[a[i]]=vis[a[i]]=0;
}
for (int i=st;i<=r;i++)
if (vis[a[i]])
{
int cnt1=sum[a[i]],cnt2=cnt[a[i]][R-1]-cnt[a[i]][L];
if (cnt2>0 && cnt2%2==0 && cnt1%2==1) res--;
if (cnt2==0 && cnt1%2==0) res++;
if (cnt2%2==1 && cnt1%2==1) res++;
sum[a[i]]=vis[a[i]]=0;
}
return res;
}
int main()
{
scanf("%d%d%d",&n,&c,&m);S=sqrt(n);
for (int i=0;i<n;i++)
scanf("%d",a+i);
Init();
for (int i=1,l,r;i<=m;i++)
{
scanf("%d%d",&l,&r);
l=(l+lastans)%n+1;
r=(r+lastans)%n+1;
if (l>r) swap(l,r);
printf("%d\n",lastans=Query(l-1,r-1));
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: