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

时间:2023-03-08 22:04:32

  容易发现要求三个区间各数出现次数的最小值。考虑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<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,a[N],b[N],cnt[N],ans[N],block;
bitset<N> f[N>>],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&?r>a.r:r<a.r);
}
}q[N];
void solve(int L,int R)
{
if (L>R) return;
int m=R-L+;
for (int i=;i<=m;i++)
{
q[i*-].i=i,q[i*-].l=c[i+L-].l1,q[i*-].r=c[i+L-].r1,q[i*-].k=q[i*-].l/block;
q[i*-].i=i,q[i*-].l=c[i+L-].l2,q[i*-].r=c[i+L-].r2,q[i*-].k=q[i*-].l/block;
q[i*].i=i,q[i*].l=c[i+L-].l3,q[i*].r=c[i+L-].r3,q[i*].k=q[i*].l/block;
}
sort(q+,q+m*+);
for (int i=;i<=m;i++) f[i].set();tot=;
memset(ans,,sizeof(ans));
memset(cnt,,sizeof(cnt));
int l=,r=;
for (int i=;i<=m*;i++)
{
ans[q[i].i]+=q[i].r-q[i].l+;
while (r<q[i].r) r++,tot[a[r]+(cnt[a[r]]++)]=;
while (l>q[i].l) l--,tot[a[l]+(cnt[a[l]]++)]=;
while (r>q[i].r) tot[a[r]+(--cnt[a[r]])]=,r--;
while (l<q[i].l) tot[a[l]+(--cnt[a[l]])]=,l++;
f[q[i].i]&=tot;
}
for (int i=;i<=m;i++)
printf("%d\n",ans[i]-*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=;i<=n;i++) b[i]=a[i]=read();
sort(b+,b+n+);
for (int i=;i<=n;i++) a[i]=lower_bound(b+,b+n+,a[i])-b-;
for (int i=;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(,m/),solve(m/+,m/),solve(m/+,m-m/),solve(m-m/+,m);
return ;
}