zoukankan      html  css  js  c++  java
  • BZOJ 4939 [Ynoi2016]掉进兔子洞(莫队+bitset)

    【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4939

    【题目大意】

      给出一个数列,每个询问给出三个区间,问除去三个区间共有的数字外,
      还剩下几个数字,注意删去的是共有的数字个数,不是数字种类,统计时候也一样

    【题解】

      首先,答案为区间长度和减去区间并数字个数和的三倍。
      所以题目转化为求区间并。很显然在开始对数据可以进行离散化。
      考虑每个数字只出现一次的情况,我们可以用bitset来统计区间某个数字是否存在,
      莫队处理查询每个区间,保存其bitset的值,最后求交即可,
      现在考虑每个数字出现多次的情况,
      我们发现经过离散的数据之间空位数量恰好可以用来标出现多次的数据,
      比如1 4 4 9 9,离散后为 1 2 2 4 4,
      我们可以将多出来的2标在3位置,4标在5位置,那么就可以用bitset统计了。
      - Me : 询问区间存不下怎么办?
      - Claris :将询问分批进行处理,单次处理25000个询问
      - Me : 超时了欸……
      - Claris : 这题卡常数,要手写bitset.
      - Me : 你的代码为什么有6.7k?
      - Claris :我分出现一次,两次和跟多次讨论
      - Me : 我……还是咸鱼吧……

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <bitset>
    #include <cmath>
    using namespace std;
    typedef unsigned long long ULL;
    const int N=100010,M=N<<2;
    int limit,n,m,pos[N],a[N],cnt[N],Ans[N],mark[N];
    struct Q{
        int l,r,id;
        friend bool operator < (const Q &a,const Q &b){
            return pos[a.l]<pos[b.l]||(pos[a.l]==pos[b.l]&&a.r<b.r);
        }
    }ask[M];
    int read(int &x){
        int f=1;char ch=getchar();x=0;
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        x*=f;
    }
    int disc[N];
    int remark(int x){
        int l=1,r=n,res=0;
        while(l<=r){
            int mid=(l+r)>>1;
            if(disc[mid]<x)l=mid+1;
            else res=mid,r=mid-1;
        }return res;
    }
    const int B=1567,K=25000;
    ULL v[B],f[K+3][B];
    int u[65537],tmp,U;
    void flip(int x){v[x>>6]^=1ULL<<(x&63);}
    void Copy(ULL*a){
        int i=0;
        for(;i+13<=U;i+=14){
            for(int j=0;j<14;j++)a[i+j]=v[i+j];
        }for(;i<=U;i++)a[i]=v[i];
    }
    void And(ULL*a){
        int i=0;
        for(;i+13<=U;i+=14){
            for(int j=0;j<14;j++)a[i+j]&=v[i+j];
        }for(;i<=U;i++)a[i]&=v[i];
    }
    void popcount(ULL x){tmp+=u[x&65535]+u[x>>16&65535]+u[x>>32&65535]+u[x>>48];}
    int count(ULL*a){
        int i=tmp=0;
        for(;i+13<=U;i+=14){
            for(int j=0;j<14;j++)popcount(a[i+j]);
        }for(;i<=U;i++)popcount(a[i]);
        return tmp;
    }
    void init(){for(int i=1;i<65536;i++)u[i]=u[i>>1]+(i&1);} 
    int main(){
        read(n); read(m);
        U=n>>6; init();
        limit=(int)sqrt(n+0.5);
        for(int i=1;i<=n;i++)read(a[i]),disc[i]=a[i],pos[i]=(i-1)/limit+1;
        sort(disc+1,disc+n+1);
        for(int i=1;i<=n;i++)a[i]=remark(a[i]);
        //for(int i=1;i<=n;i++)printf("%d
    ",a[i]); 
        int pos=0,l=1,r=0;
        while(pos<m){
            int tot=0;
            for(int i=1;i<=25000&&i+pos<=m;i++){
                tot+=3;
                Ans[i]=0;
                mark[i]=0;
                read(ask[i*3-2].l); read(ask[i*3-2].r); ask[i*3-2].id=i;
                read(ask[i*3-1].l); read(ask[i*3-1].r); ask[i*3-1].id=i;
                read(ask[i*3].l); read(ask[i*3].r); ask[i*3].id=i;
                Ans[i]+=ask[i*3-2].r-ask[i*3-2].l+1;
                Ans[i]+=ask[i*3-1].r-ask[i*3-1].l+1;
                Ans[i]+=ask[i*3].r-ask[i*3].l+1;
            }sort(ask+1,ask+tot+1);
            for(int i=1;i<=tot;i++){
                for(;r<ask[i].r;r++){flip(a[r+1]+cnt[a[r+1]]);cnt[a[r+1]]++;}
                for(;l>ask[i].l;l--){flip(a[l-1]+cnt[a[l-1]]);cnt[a[l-1]]++;}
                for(;l<ask[i].l;l++){cnt[a[l]]--;flip(a[l]+cnt[a[l]]);}
                for(;r>ask[i].r;r--){cnt[a[r]]--;flip(a[r]+cnt[a[r]]);}
                if(mark[ask[i].id])And(f[ask[i].id]);
                else Copy(f[ask[i].id]),mark[ask[i].id]=1;
            }tot/=3;
            for(int i=1;i<=tot;i++)printf("%d
    ",Ans[i]-3*count(f[i])); 
            pos+=tot;
        }return 0;
    }
  • 相关阅读:
    SQL Server, Timeout expired.all pooled connections were in use and max pool size was reached
    javascript 事件调用顺序
    Best Practices for Speeding Up Your Web Site
    C语言程序设计 使用VC6绿色版
    破解SQL Prompt 3.9的几步操作
    Master page Path (MasterPage 路径)
    几个小型数据库的比较
    CSS+DIV 完美实现垂直居中的方法
    由Response.Redirect引发的"Thread was being aborted. "异常的处理方法
    Adsutil.vbs 在脚本攻击中的妙用
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj4939.html
Copyright © 2011-2022 走看看