【莫队】【P3901】 数列找不同

Description

现在有一个长度为 n 的数列 A1 , A2  An  Q 个询问 [li , ri] ,每次询问区间内是否有元素相同

Input

第一行有两个整数 N,Q ,

第二行有 n 个整数,代表这个序列

以下 Q 行每行两个整数,代表询问区间

Output

对每个询问输出一行 Yes  No 

Hint

Forall:

1  n , Q  105 , 1  Ai  N , 1  li  ri  N

Solution

看到这题发现可以用莫队做。然鹅统计区间出现次数平方的题写腻了,而开桶和位向量的做法又很麻烦,于是我就YY了一个更加麻烦的做法。

发现我们可以在莫队维护区间信息的时候维护区间中所有元素出现次数之积。因为乘1等价于没有乘,我们对于没有出现的元素也乘1。这个值在指针移动时是支持修改的:只要在去掉该位置贡献的时候除掉当前的出现次数,然后将这个位置的出现次数1,再乘回去即可。增加一个位置贡献的方法同理。当询问的区间出现次数积为1时,即为没有出现重复,否则为出现重复。

但是考虑这么做在极端数据,比如前n2个数出现了2次,后n2个数没有出现的时候,积是2n2次方,显然存不下。这时考虑NOIP2014解方程,我们只需要对多个形如1******7的大质数取模,当所有取模后的答案都为1是,我们认为积是1,否则积显然不是1

于是先O(n)筛一下逆元再莫队就好了。

Code

这个代码写的好丑啊……其实可以美化美化然而我懒得写了

#include<cmath>
#include<cstdio>
#include<algorithm>
#ifdef ONLINE_JUDGE
#define puts(o) \
puts("I am a cheater!")
#define freopen(a,b,c)
#endif
#define rg register
#define ci const int
#define cl const long long

typedef long long int ll;

template <typename T>
inline void qr(T &x) {
	rg char ch=getchar(),lst=' ';
	while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
	while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	if(lst == '-') x=-x;
}

namespace IO {
	char buf[120];
}

template <typename T>
inline void qw(T x,const char aft,const bool pt) {
	if(x < 0) {x=-x,putchar('-');}
	rg int top=0;
	do {IO::buf[++top]=x%10+'0';} while(x/=10);
	while(top) putchar(IO::buf[top--]);
	if(pt) putchar(aft);
}

const int maxn = 100010;
const int ccnt = 6;

int n,q;
int MU[maxn],belong[maxn],bk[maxn];
int inv[8][maxn];

struct Ask {
	int l,r,num;
	bool ans;
	inline bool operator<(const Ask &_others) const {
		if(belong[this->l] != belong[_others.l]) return this->l < _others.l;
		if(belong[this->l] & 1) return this->r < _others.r;
		else return this->r > _others.r;
	}
};
Ask ask[maxn];

inline bool cmp(const Ask &_a,const Ask &_b) {
	return _a.num < _b.num;
}

struct C {
	int mod;
	int ans;
	C(int _x=0) {mod=_x,ans=1;}
};
C CU[8];

void GetInv(ci,ci);

int main() {
	freopen("1.in","r",stdin);
	qr(n);qr(q);
	for(rg int i=1;i<=n;++i) qr(MU[i]);
	for(rg int i=1,sn=sqrt(n);i<=n;++i) belong[i]=i/sn;
	for(rg int i=1;i<=q;++i) {
		qr(ask[i].l);qr(ask[i].r);ask[i].num=i;
	}
	CU[1]=C(1000000007);CU[2]=C(1000000009);CU[3]=C(19260817);CU[4]=C(998244353);CU[5]=C(10000007);
	for(int i=1;i<ccnt;++i) GetInv(CU[i].mod,i);
	std::sort(ask+1,ask+1+q);
	int prel=ask[1].l,prer=ask[1].l-1;
#define jd(o) (bk[MU[o]] > 1)
	for(rg int i=1;i<=q;++i) {
		int l=ask[i].l,r=ask[i].r;
		while(prel < l) {
			if(jd(prel)) {
				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*inv[j][bk[MU[prel]]]%CU[j].mod;
			}
			--bk[MU[prel]];
			if(jd(prel)) {
				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*bk[MU[prel]]%CU[j].mod;
			}
			++prel;
		}
		while(prel > l) {
			--prel;
			if(jd(prel)) {
				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*inv[j][bk[MU[prel]]]%CU[j].mod;
			}
			++bk[MU[prel]];
			if(jd(prel)) {
				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*bk[MU[prel]]%CU[j].mod;
			}
		}
		while(prer < r) {
			++prer;
			if(jd(prer)) {
				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*inv[j][bk[MU[prer]]]%CU[j].mod;
			}
			++bk[MU[prer]];
			if((jd(prer))) {
				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*bk[MU[prer]]%CU[j].mod;
			}
		}
		while(prer > r) {
			if(jd(prer)) {
				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*inv[j][bk[MU[prer]]]%CU[j].mod;
			}
			--bk[MU[prer]];
			if(jd(prer)) {
				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*bk[MU[prer]]%CU[j].mod;
			}
			--prer;
		}
		bool _ans=true;
		for(rg int j=1;j<ccnt;++j) if(CU[j].ans != 1) {
			_ans=false;break;
		}
		ask[i].ans=_ans;
	}
#undef jd
	std::sort(ask+1,ask+1+q,cmp);
	for(rg int i=1;i<=q;++i) 
		if(ask[i].ans) puts("Yes");
		else puts("No");
	return 0;
}

void GetInv(ci mod,ci cur) {
	inv[cur][1]=1;
	for(rg int i=2;i<=n;++i) inv[cur][i]=1ll*(mod-mod/i)*inv[cur][mod%i]%mod;
}

Summary

貌似这次没啥好summary的

posted @   一扶苏一  阅读(195)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示