[Luogu P4688] [Ynoi2016] 掉进兔子洞

\(\text{Problem}:\)题目链接

\(\text{Solution}:\)

\(bitset\) 优化莫队。现在考虑的是三个区间有多少个数相同,而用 \(bitset\) 可以快速求出三个区间有多少种数相同。

发现可以离散化,但是不能去重,这样我们用 \(lower\)_\(bound\) 得到每个位置的值,将原序列排序后,如果 \(a_{y}\) 是最小的大于 \(a_{x}\) 的数,那么有 \(y=x+cnt_{x}\)。我们每次在 \(bitset\) 中使得 \(x+cnt_{x}-1\) 这一位变成 \(1\) 即可,这样就可以将一个数出现不同的次数在 \(bitset\) 中表现为不同的下标,就可以得到答案。

注意本题卡空间,可以将查询分为若干块进行操作。

\(\text{Code}:\)

#include <bits/stdc++.h>
//#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
using namespace std; const int N=100010, M=23333;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,m,a[N],ta[N],blk,bl[N],Q,cnt[N],W[N];
struct Query
{
	int l,r,id;
}q[N];
bitset<N> Ans[M+2],res;
inline bool cp(Query x,Query y)
{
	if(bl[x.l]^bl[y.l]) return bl[x.l]<bl[y.l];
	if(bl[x.l]&1) return x.r<y.r;
	else return x.r>y.r;
}
inline void Add(int x)
{
	res.set(a[x]+cnt[a[x]]);
	cnt[a[x]]++;
}
inline void Del(int x)
{
	cnt[a[x]]--;
	res.reset(a[x]+cnt[a[x]]);
}
inline void Solve()
{
	memset(cnt,0,sizeof(cnt));
	Q=0, res.reset();
	for(ri int i=0;i<M&&m;i++)
	{
		m--, Q++, Ans[Q].set();
		W[Q]=0;
		for(ri int j=1;j<=3;j++)
		{
			q[i*3+j].l=read(), q[i*3+j].r=read();
			q[i*3+j].id=Q;
			W[Q]+=q[i*3+j].r-q[i*3+j].l+1;
		}
	}
	sort(q+1,q+1+Q*3,cp);
	int L,R; L=1, R=0;
	for(ri int i=1;i<=Q*3;i++)
	{
		while(L>q[i].l) L--, Add(L);
		while(R<q[i].r) R++, Add(R);
		while(L<q[i].l) Del(L), L++;
		while(R>q[i].r) Del(R), R--;
		Ans[q[i].id]&=res;
	}
	for(ri int i=1;i<=Q;i++) printf("%d\n",W[i]-(int)Ans[i].count()*3);
}
signed main()
{
	n=read(), m=read();
	for(ri int i=1;i<=n;i++) a[i]=ta[i]=read();
	sort(ta+1,ta+1+n);
	for(ri int i=1;i<=n;i++) a[i]=lower_bound(ta+1,ta+1+n,a[i])-ta;
	blk=(int)sqrt(n);
	for(ri int i=1;i<=n;i++) bl[i]=(i-1)/blk+1;
	while(m) Solve();
	return 0;
}
posted @ 2021-02-22 15:25  zkdxl  阅读(47)  评论(1编辑  收藏  举报