专栏文章

P3901

P3901题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min4r7fr
此快照首次捕获于
2025/12/01 20:33
3 个月前
此快照最后确认于
2025/12/01 20:33
3 个月前
查看原文

题意

有一个长度为 nn 的序列 aaqq 次询问,问 [l,r][l,r] 中是不是互不相同。

题解

题解区里一车子莫队,但我不会莫队,用一个非常神秘的算法交一发过了,故写题解。
lstilst_{i}aa 中与其相同的上一个数的位置,如果一个区间不合法,他肯定同时包含 lstilst_{i}ii
然后就可以把所有区间拉出来,按照左端点排序并离线处理。
ii1n1 \sim n 从小到大枚举,如果遇到左端点就把这个区间加入到一个容器里,遇到右端点就把这个区间从容器里退出。
重头戏来了:每遇到一个 ii,就把看容器里的区间有几个其左节点在 lstilst_{i} 前,那么这些区间里肯定都不互不相同,答案就是 No
跑完一遍没有跑出来上面这个情况的,答案就是 Yes
至于这个容器……可以用 set 啊,又满足加入,还满足删除,甚至可以按照左端点把加入的节点排序!
加个具体实现:
枚举 i[1,n]i \in [1,n],遇到一个左端点为 ii,将其加入 set 里。
然后对于 ii,枚举左端点在 lstilst_{i} 前的所有区间将其退掉,然后让其答案为 No,借助 set 强大的排序功能,可以很轻松的找这些。
最后退掉右端点在 ii 的,用一个堆将所有在 set 里的按右端点从小到大排序,那么如果存在,右端点在 ii 的一定在堆顶(右端点小于 ii 的已经被退了),接着就把这些在 set 里使用 find() 函数找一下,找到就退,找不到(可能之前答案已经设定了)就不用退了。
STL 很好玩吧!
然后就做完了,复杂度 O(nlogq)O(n \log q)

代码

CPP
#include<bits/stdc++.h>
#define pii pair<int,int>
#define si set<pair<int,int> >::iterator
using namespace std;
const int N=1e5+5;
int n,q;
int a[N],lst[N],lsta[N],reff[N];
struct query {
	int l,r,id;
	bool ans;
} s[N];
bool cmp(query a,query b) {
	return a.l<b.l;
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>q;
	for(int i=1;i<=n;i++) {
		cin>>a[i];
		lst[i]=lsta[a[i]];
		lsta[a[i]]=i;
	}
	for(int i=1;i<=q;i++) cin>>s[i].l>>s[i].r,s[i].id=i;
	sort(s+1,s+1+q,cmp);
	for(int i=1;i<=q;i++) reff[s[i].id]=i;
	set<pii> S;
	priority_queue<pii> del;
	int x=1;
	for(int i=1;i<=n;i++) {
		while(i==s[x].l) S.insert({s[x].l,x}),del.push({-s[x].r,x}),x++;
		//加入左端点在 i 的区间 
		for(si j=S.begin(),ERASE;(*j).first<=lst[i]&&j!=S.end();) { //左端点在 lst[i] 及以前的答案都是 No
			s[(*j).second].ans=1;
			ERASE=j,j++;
			S.erase(ERASE); //删掉,让每个区间至多被判一次,这样复杂度正确的
		}
		while(del.size()&&-del.top().first==i) {
			int xx=del.top().second;
			del.pop();
			si FIND=S.find({s[xx].l,xx});
			if(FIND!=S.end()) S.erase(FIND);
		} //堆会按照第一关键字排序,可以轻松把右端点在 i 的退掉 
	}
	for(int i=1;i<=q;i++) {
		if(s[reff[i]].ans) puts("No");
		else puts("Yes");
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...