BZOJ4939 Ynoi2016掉进兔子洞(莫队+bitset)

  容易发现要求三个区间各数出现次数的最小值。考虑bitset,不去重离散化后and一发就可以了。于是莫队求出每个区间的bitset。注意空间开不下,做多次即可。输出的东西错了都能调一年服了我了。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<bitset>
using namespace std;
#define ll long long
#define N 100050
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,a[N],b[N],cnt[N],ans[N],block;
bitset<N> f[N>>2],tot;
struct data{int l1,r1,l2,r2,l3,r3;
}c[N];
struct data2
{
    int l,r,i,k;
    bool operator <(const data2&a) const
    {
        return k<a.k||k==a.k&&(k&1?r>a.r:r<a.r);
    }
}q[N];
void solve(int L,int R)
{
    if (L>R) return;
    int m=R-L+1;
    for (int i=1;i<=m;i++)
    {
        q[i*3-2].i=i,q[i*3-2].l=c[i+L-1].l1,q[i*3-2].r=c[i+L-1].r1,q[i*3-2].k=q[i*3-2].l/block;
        q[i*3-1].i=i,q[i*3-1].l=c[i+L-1].l2,q[i*3-1].r=c[i+L-1].r2,q[i*3-1].k=q[i*3-1].l/block;
        q[i*3].i=i,q[i*3].l=c[i+L-1].l3,q[i*3].r=c[i+L-1].r3,q[i*3].k=q[i*3].l/block;
    }
    sort(q+1,q+m*3+1);
    for (int i=1;i<=m;i++) f[i].set();tot=0;
    memset(ans,0,sizeof(ans));
    memset(cnt,0,sizeof(cnt));
    int l=1,r=0;
    for (int i=1;i<=m*3;i++)
    {
        ans[q[i].i]+=q[i].r-q[i].l+1;
        while (r<q[i].r) r++,tot[a[r]+(cnt[a[r]]++)]=1;
        while (l>q[i].l) l--,tot[a[l]+(cnt[a[l]]++)]=1;
        while (r>q[i].r) tot[a[r]+(--cnt[a[r]])]=0,r--;
        while (l<q[i].l) tot[a[l]+(--cnt[a[l]])]=0,l++;
        f[q[i].i]&=tot;
    }
    for (int i=1;i<=m;i++)
    printf("%d\n",ans[i]-3*f[i].count());
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj4939.in","r",stdin);
    freopen("bzoj4939.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read(),m=read();block=sqrt(n);
    for (int i=1;i<=n;i++) b[i]=a[i]=read();
    sort(b+1,b+n+1);
    for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+n+1,a[i])-b-1;
    for (int i=1;i<=m;i++) c[i].l1=read(),c[i].r1=read(),c[i].l2=read(),c[i].r2=read(),c[i].l3=read(),c[i].r3=read();
    solve(1,m/4),solve(m/4+1,m/2),solve(m/2+1,m-m/4),solve(m-m/4+1,m);
    return 0;
}

 

posted @ 2018-12-01 23:24  Gloid  阅读(147)  评论(0编辑  收藏  举报