您的位置:首页 > 其它

【分块】bzoj2821 作诗(Poetize)

2014-09-09 20:48 302 查看
分块,预处理出:

①第i块到第j块之间的偶数值的种类数。

②在前i块中,每个值出现的次数。(前缀和)(差分)

每次询问时,对于不在整块中的元素,进行暴力转移。

注意:减少memset的使用,千万不要写100000个memset,否则会TLE,宁愿每次询问之后O(sqrt(n))地一个个减掉那个记录每个值出现次数的临时数组。

Code:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,kind,m,a[100001],sz,sum,num[100001],l[320],r[320],w[320][320];
int Time[100001],ans,x,y;
int ev[100001][320];
void makeev()
{
for(int i=1;i<=n;i++)
for(int j=num[i];j<=sum;j++)
ev[a[i]][j]++;
}
inline int getsum(const int &v,const int &L,const int &R){return ev[v][R]-ev[v][L-1];}
void makeblock()
{
for(sum=1;sum*sz<n;sum++)
{
l[sum]=(sum-1)*sz+1;
r[sum]=sum*sz;
for(int i=l[sum];i<=r[sum];i++)
num[i]=sum;
}
l[sum]=sz*(sum-1)+1;
r[sum]=n;
for(int i=l[sum];i<=r[sum];i++)
num[i]=sum;
}
void init()
{
for(int i=1;i<=sum;i++)
{
memset(Time,0,sizeof(Time));
for(int j=i;j<=sum;j++)
{
w[i][j]=w[i][j-1];
for(int k=l[j];k<=r[j];k++)
{
Time[a[k]]++;
if(!(Time[a[k]]&1))w[i][j]++;
else if(Time[a[k]]!=1)w[i][j]--;
}
}
}
}
int res,CH[20],Num;char c;
inline int G()
{
res=0;c='*';
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9'){res=res*10+(c-'0');c=getchar();}
return res;
}
inline void P(int x)
{
if(!x){putchar('0');putchar('\n');return;}Num=0;
while(x>0){CH[++Num]=x%10;x/=10;}
while(Num)putchar(CH[Num--]+48);
putchar('\n');
}
int main()
{
n=G();kind=G();m=G();
sz=sqrt(n);
for(int i=1;i<=n;i++)a[i]=G();
makeblock();init();makeev();
memset(Time,0,sizeof(Time));
for(int i=1;i<=m;i++)
{
x=G();y=G();x=(x+ans)%n+1;y=(y+ans)%n+1;if(x>y)swap(x,y);
ans=w[num[x]+1][num[y]-1];
if(num[x]+1>=num[y])
{
for(int j=x;j<=y;j++)
{
Time[a[j]]++;
if(!(Time[a[j]]&1))ans++;
else if(Time[a[j]]!=1)ans--;
}
for(int j=x;j<=y;j++)Time[a[j]]--;
}
else
{
for(int j=x;j<=r[num[x]];j++)
{
Time[a[j]]++;
if(!((Time[a[j]]+getsum(a[j],num[x]+1,num[y]-1))&1))ans++;
else if(Time[a[j]]+getsum(a[j],num[x]+1,num[y]-1)!=1)ans--;
}
for(int j=l[num[y]];j<=y;j++)
{
Time[a[j]]++;
if(!((Time[a[j]]+getsum(a[j],num[x]+1,num[y]-1))&1))ans++;
else if(Time[a[j]]+getsum(a[j],num[x]+1,num[y]-1)!=1)ans--;
}
for(int j=x;j<=r[num[x]];j++)Time[a[j]]--;
for(int j=l[num[y]];j<=y;j++)Time[a[j]]--;
}
P(ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: