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; }