zoukankan      html  css  js  c++  java
  • 【bzoj2821】作诗(Poetize)

    分块做法*

    ps:第一篇博客,有点小激动,有错误大佬别怼我;

    题目大概是这样的;
    类似于区间众数,在询问的区间中统计出现过偶数次的元素和。
    那么这种类型的题目分块比暴力优越在哪??是的,只是因为预处理而已;

    先用f[i][j]统计出:第i块 到 第j块中询问的答案;

    对于不完整的块,我们最多做不超过块大小两倍,时间上有保证;

    查询*

    对于区间[a,b],可分为三个部分:1.[a,min(b,bl[a]*blo], 2.[bl[a]*blo+1,(bl[b-1]*blo], 3.[bl[b-1]*blo+1,b];

    注意到第二部分的答案是已知的,那么影响结果的只能是1,3部分的元素;

    每个暴力查询他在大区间中出现的次数,判断他在完整的块里是否被统计过,修改rtn;

    应该就这些,另外对于查询他出现的次数,二分就行了,用vector记录这个元素所有出现的位置,看哪些在[a,b]中;

    好了,代码如xia:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <vector>
    #include <algorithm>
    #include <map>
    #define LL long long
    using namespace std;
    
    int read(){
        int rtn=0,f=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch<='9'&&ch>='0')rtn=rtn*10+ch-'0',ch=getchar();
        return rtn*f;
    }
    
    int n,q,c,id,lastans,m,v[100010],blo,flag[100010],cnt[100010],bl[100010],f[1505][1505];
    vector<int>ve[100010];//不用vector写法复杂一些,蒟蒻不会; 
    //如果按照sqrt(n/log(n)*log(2))分,块的数量比原来增多,; 
    void reset(int x){
        int l=(x-1)*blo+1,tot=0;
        for(int i=l;i<=n;i++)cnt[v[i]]=0;
        for(int i=l;i<=n;i++){
            int t=bl[i];
            cnt[v[i]]++;
            if(cnt[v[i]]==1){
                f[x][t]=tot;
                continue;
            }
            if(!(cnt[v[i]]&1))tot++;
            if(cnt[v[i]]&1)tot--;
            f[x][t]=tot;
            //预处理,偶数加一,奇数减一,等于一的时候特判; 
        }
    }
    
    int Query(int l,int r,int x){
        return (upper_bound(ve[x].begin(),ve[x].end(),r)-
                lower_bound(ve[x].begin(),ve[x].end(),l));
    }
    
    int query(int a,int b){
        int ans=0,l=bl[a]*blo+1,r=(bl[b]-1)*blo;
        if(bl[a]==bl[b]||bl[a]+1==bl[b]){
            for(int i=a;i<=b;i++){
                if(flag[v[i]])continue;
                int t1=Query(a,b,v[i]);
                if(!(t1&1)){flag[v[i]]=1;ans++;}
            }
            for(int i=a;i<=b;i++)flag[v[i]]=0;
        }
        else{
            ans=f[bl[a]+1][bl[b]-1];
            for(int i=a;i<=bl[a]*blo;i++){
                if(flag[v[i]])continue;
                int t1=Query(a,b,v[i]);
                int t2=Query(l,r,v[i]);
                if(!(t1&1))
                    if(t2&1||!t2)ans++;
                if(t1&1)
                    if(!(t2&1)&&t2)ans--;
                flag[v[i]]=1; 
            }
            for(int i=(bl[b]-1)*blo+1;i<=b;i++){
                if(flag[v[i]])continue;
                int t1=Query(a,b,v[i]);
                int t2=Query(l,r,v[i]);
                if(!(t1&1))
                    if(t2&1||!t2)ans++;
                if(t1&1)
                    if(!(t2&1)&&t2)ans--;
                flag[v[i]]=1;
            } 
            for(int i=a;i<=bl[a]*blo;i++)flag[v[i]]=0;
            for(int i=(bl[b]-1)*blo+1;i<=b;i++)flag[v[i]]=0; 
        }
        return ans;
    
    }
    
    int main()
    {
        n=read(),c=read(),q=read();
        blo=sqrt((double)n/log((double)n)*log(2));//注意块大小 
        for(int i=1;i<=n;i++){
            v[i]=read();
            bl[i]=(i-1)/blo+1;
            ve[v[i]].push_back(i);
        }
        if(n%blo)m=n/blo+1;
        else m=n/blo;
        for(int i=1;i<=m;i++)reset(i);
        for(int i=1;i<=q;i++){
            int x=read(),y=read();
            x=(x+lastans)%n+1,y=(y+lastans)%n+1;
            if(x>y)swap(x,y);
            lastans=query(x,y);
            printf("%d
    ",lastans);
        }
        return 0;
    }
  • 相关阅读:
    springboot配置大全
    springboot上传文件时500错误,提示临时目录无效
    Springboot上传文件临时目录无效
    SpringBoot 文件上传临时文件路径问题
    SpringBoot 上传文件到linux服务器 异常java.io.FileNotFoundException: /tmp/tomcat.50898……解决方案
    tomcat下的work目录和temp目录
    Http协议报文格式
    multipart/form-data与application/octet-stream的区别、application/x-www-form-urlencoded
    Nginx的三种应用场景介绍
    SpringBoot: 浅谈文件上传和访问的坑 (MultiPartFile)
  • 原文地址:https://www.cnblogs.com/DexterYsw/p/7136256.html
Copyright © 2011-2022 走看看