两道莫队水题

Luogu P2709 小B的询问

莫队水题一道,比Luogu P1494 [国家集训队]小Z的袜子还简单的多

先将询问排个序,然后每次添加(删除)元素的时候先前去之前的再更新后面的即可。

水题不想讲,CODE

#include<cstdio>
#include<cctype>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=50005;
struct data
{
	int l,r,id; long long ans;
}q[N];
int a[N],n,m,k,blk[N],size,L,R,cnt[N];
long long res;
inline char tc(void)
{
	static char fl[100000],*A=fl,*B=fl;
	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
	x=0; char ch; while (!isdigit(ch=tc()));
	while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline void write(long long x)
{
	if (x>9) write(x/10);
	putchar(x%10+'0');
}
inline bool cmp1(data a,data b)
{
	return blk[a.l]^blk[b.l]?(blk[a.l]<blk[b.l]):(blk[a.l]&1?a.r<b.r:a.r>b.r);
}
inline bool cmp2(data a,data b)
{
	return a.id<b.id;
}
inline void add(int col)
{
	res-=1LL*cnt[col]*cnt[col]; ++cnt[col]; res+=cnt[col]*cnt[col];
}
inline void del(int col)
{
	res-=1LL*cnt[col]*cnt[col]; --cnt[col]; res+=1LL*cnt[col]*cnt[col];
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	register int i; read(n); read(m); read(k); size=sqrt(n);
	for (i=1;i<=n;++i) read(a[i]),blk[i]=(i-1)/size+1;
	for (i=1;i<=m;++i) read(q[i].l),read(q[i].r),q[i].id=i;
	sort(q+1,q+m+1,cmp1); L=q[1].l; R=q[1].r;
	for (i=L;i<=R;++i) add(a[i]); q[1].ans=res;
	for (i=2;i<=m;++i)
	{
		while (L>q[i].l) add(a[--L]); while (L<q[i].l) del(a[L++]);
		while (R<q[i].r) add(a[++R]); while (R>q[i].r) del(a[R--]);
		q[i].ans=res;
	}
	for (sort(q+1,q+m+1,cmp2),i=1;i<=m;++i)
	write(q[i].ans),putchar('
');
	return 0;
}

Luogu P4113 [HEOI2012]采花

这其实是一道很好的练习主席树的题目,不过由于我比较懒不会,所以也就写了莫队。

题目大意:给出(n)个数,求区间出现次数(ge2)的数的个数。

还是莫队啦,每次添加(删除)时对于与(2)的大小关系特判一下即可,难度也很低。

不过可以只能拿原来数据的100分,后面的一个Subtask老实用主席树吧

CODE

#include<cstdio>
#include<cctype>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=300005;
struct data
{
	int l,r,id,ans;
}q[N];
int a[N],n,m,k,blk[N],size,L,R,cnt[N];
long long res;
inline char tc(void)
{
	static char fl[100000],*A=fl,*B=fl;
	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
	x=0; char ch; while (!isdigit(ch=tc()));
	while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline void write(int x)
{
	if (x>9) write(x/10);
	putchar(x%10+'0');
}
inline bool cmp1(data a,data b)
{
	return blk[a.l]<blk[b.l]||(blk[a.l]==blk[b.l]&&(blk[a.l]&1?a.r<b.r:a.r>b.r));
}
inline bool cmp2(data a,data b)
{
	return a.id<b.id;
}
inline void add(int col)
{
	if (++cnt[col]==2) ++res;
}
inline void del(int col)
{
	if (--cnt[col]==1) --res;
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	register int i; read(n); read(k); read(m); size=sqrt(n);
	for (i=1;i<=n;++i) read(a[i]),blk[i]=(i-1)/size+1;
	for (i=1;i<=m;++i) read(q[i].l),read(q[i].r),q[i].id=i;
	sort(q+1,q+m+1,cmp1); L=q[1].l; R=q[1].r;
	for (i=L;i<=R;++i) add(a[i]); q[1].ans=res;
	for (i=2;i<=m;++i)
	{
		while (L>q[i].l) add(a[--L]); while (L<q[i].l) del(a[L++]);
		while (R<q[i].r) add(a[++R]); while (R>q[i].r) del(a[R--]);
		q[i].ans=res;
	}
	for (sort(q+1,q+m+1,cmp2),i=1;i<=m;++i)
	write(q[i].ans),putchar('
');
	return 0;
}
原文地址:https://www.cnblogs.com/cjjsb/p/9550893.html