P4135 作诗——分块

Posted zinn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4135 作诗——分块相关的知识,希望对你有一定的参考价值。

题目:https://www.luogu.org/problemnew/show/P4135

分块大法;

块之间记录答案,每一块记录次数前缀和;

注意每次把桶中需要用到位置赋值就好了;

为什么加了特判会 T 一个点?

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int const maxn=1e5+5;
int n,c,m,mod,a[maxn],ans,blk[maxn],base,t[maxn],cnt[320][maxn],bst[320],bed[320],f[320][320];
void pre(int x)
{
    int tmp=0,tem=x;
    memset(t,0,sizeof t);
    for(int i=bst[x];i<=n;i++)
    {
        t[a[i]]++;
        if(t[a[i]]%2==0)tmp++;
        else if(t[a[i]]>1)tmp--;
        if(i==bed[tem])f[x][tem]=tmp,tem++;
    }
}
int main()
{
    scanf("%d%d%d",&n,&c,&m); 
    base=sqrt(n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),blk[i]=(i-1)/base+1;
    for(int i=1;i<=blk[n];i++)bst[i]=(i-1)*base+1,bed[i]=min(n,i*base);
    for(int i=1;i<=blk[n];i++)pre(i);
    for(int i=1;i<=blk[n];i++)
    {
        for(int k=1;k<=c;k++)cnt[i][k]=cnt[i-1][k];
        for(int j=bst[i];j<=bed[i];j++)cnt[i][a[j]]++;
    }    
    for(int i=1,l,r;i<=m;i++)
    {
        scanf("%d%d",&l,&r);
        l=(l+ans)%n+1; r=(r+ans)%n+1;
        if(l>r)swap(l,r);
//        if(l==r){printf("0
"); ans=0; continue;}//ans=0!!!  //加特判变慢了??? 
        ans=0;
        if(blk[l]==blk[r])
        {
            for(int j=l;j<=r;j++)t[a[j]]=0;
            for(int j=l;j<=r;j++)
            {
                t[a[j]]++;
                if(t[a[j]]%2==0)ans++;
                else if(t[a[j]]>1)ans--;
            }
            printf("%d
",ans);
        }
        else
        {
            if(blk[r]>blk[l]+1)ans=f[blk[l]+1][blk[r]-1];
            for(int j=l;j<=bed[blk[l]];j++)t[a[j]]=cnt[blk[r]-1][a[j]]-cnt[blk[l]][a[j]];
            for(int j=bst[blk[r]];j<=r;j++)t[a[j]]=cnt[blk[r]-1][a[j]]-cnt[blk[l]][a[j]];
            for(int j=l;j<=bed[blk[l]];j++)
            {
                t[a[j]]++;
                if(t[a[j]]%2==0)ans++;
                else if(t[a[j]]>1)ans--;
            }
            for(int j=bst[blk[r]];j<=r;j++)
            {
                t[a[j]]++;
                if(t[a[j]]%2==0)ans++;
                else if(t[a[j]]>1)ans--;
            }
            printf("%d
",ans);
        }    
    }
    return 0;
}

 

以上是关于P4135 作诗——分块的主要内容,如果未能解决你的问题,请参考以下文章

P4135 作诗

作诗(分块)

BZOJ2821作诗(Poetize) 分块

BZOJ2821作诗(Poetize) 分块

BZOJ 2821作诗(Poetize) 分块

BZOJ 2821: 作诗(Poetize) | 分块