zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    web前端网站收藏
    wordpress安装(ubuntu+nginx+php+mariadb)
    硬盘分区表知识——详解硬盘MBR
    useradd添加用户
    闭包closure this
    什么是同步加载与异步加载
    css 两个span标签在同一行,高度不一样
    CSS label之间存在间距
    JS中如何跳出循环/结束遍历
    el-checkbox-group 无法选中
  • 原文地址:https://www.cnblogs.com/Zinn/p/9302300.html
Copyright © 2011-2022 走看看