QOJ 17177. Wonderful Interval 2 题解

题目链接

因为这道题学了 ODT 。

先将条件转化一下,不难发现为 \(L \le i \le R\),满足 \([a_i,b_i] \in [b_l,\dots,b_r]\)

由于 \(b_i\) 肯定在 \([b_l \dots b_r]\) 中,因此可以转化为两个集合比大小。

令集合 \(S\) 为所有 \([a_i,b_i]\) 的交集,\(T\)\([b_l,\dots,b_r]\) 的交集。那么就是当 \(|S| = |T|\) 时,结果为真。

考虑使用 ds 进行维护。尝试对 \(r\) 进行扫描线,刻画一下结果的变化。\(|T|\) 的修改是简单的,用 BIT 维护区间出现数的种类就行。主要是 \(|S|\) 的问题。

考虑使用 BIT + ODT 进行 \(|S|\) 的维护,表示区间内的 \(|S|\) 的大小。ODT 负责区间推平,把位置推到 \(r\) 上,BIT 则是负责记录。做完了。

Code

实现感觉细节很多。

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
#define IT set<node>::iterator
const int N = 250000 + 10;
const int M = 1000000 + 10;
int a[N],b[N];
int lst[M];
vector< pair<int,int> > ques[N];
int lsh[M];
int n;
int tot;
int ans[N];
struct sgt{
	int tre[N];
	int lowbit(int x){return x & (-x);}
	void update(int x,int k){if(x == 0) return ;while(x <= n){tre[x] += k;x += lowbit(x);}}
	int query(int x){if(x == 0) return 0;int sum = 0;while(x){sum += tre[x];x -= lowbit(x);}return sum;}
	int query(int l,int r){return query(r) - query(l-1);}
}BIT[2];
struct ODT{
	struct node{
		int l,r;
		LL v;
		node(int L,int R=-1,int v=0): l(L),r(R),v(v) {}
		bool operator < (const node& o) const{return l < o.l;}
	};
	set<node> st;
	IT split(int pos){
		IT it = st.lower_bound(node(pos));
		if(it != st.end() && it->l == pos) return it;
		if(it == st.begin()) return st.end();
		it -- ;
		int L,R;L = it->l;R = it->r ;LL val = it->v;
		if(pos < L || pos >= R) return st.end();
		st.erase(it);
		st.insert(node(L,pos,val));
		return st.insert(node(pos,R,val)).first;
	}
	void assign(int l,int r,int pos){
		IT itr = split(r);
		IT itl = split(l);
		if(!(itl == st.end() || itr == st.end())){
			for(;itl!=itr;itl++){
				BIT[0].update(itl->v,-(itl->r - itl->l));
			}
			itl = split(l);
			st.erase(itl,itr);
		}
		st.insert(node(l,r,pos));
		BIT[0].update(pos,r-l);
		return ;
	}
}odt;
vector<int> array_operation(vector<int> A, vector<int> B, vector<int> L,vector<int> R){
	vector<int> Ans;
	n = A.size();
	for(int i=1;i<=n;i++){
		a[i] = A[i-1] + 1;
		lsh[++tot] = a[i];
	}
	for(int i=1;i<=n;i++){
		b[i] = B[i-1] + 1;
		lsh[++tot] = b[i];
	}
	sort(lsh+1,lsh+1+tot);
	int len = unique(lsh+1,lsh+1+tot) - lsh - 1;
	for(int i=1;i<len;i++){
		if(lsh[i] != lsh[i+1] - 1) lsh[++tot] = lsh[i]+1;
	}
	sort(lsh+1,lsh+1+tot);
	tot = unique(lsh+1,lsh+1+tot) - lsh - 1;
	for(int i=1;i<=n;i++){
		a[i] = lower_bound(lsh+1,lsh+1+tot,a[i]) - lsh;
		b[i] = lower_bound(lsh+1,lsh+1+tot,b[i]) - lsh;
	}
	odt.st.insert(ODT::node(1,tot+2,0));
	int Q = L.size();
	for(int i=0;i<Q;i++){ques[R[i]+1].push_back({L[i]+1,i+1});}
	for(int r=1;r<=n;r++){
		odt.assign(a[r],b[r]+1,r);
		if(lst[b[r]]){BIT[1].update(lst[b[r]],-1);}
		BIT[1].update(r,1);
		lst[b[r]] = r;
		for(auto [l,id] : ques[r]){
			if(BIT[0].query(l,r) == BIT[1].query(l,r)) ans[id] = 1;
		}
	}
	for(int i=1;i<=Q;i++)
		Ans.push_back(ans[i]);
	return Ans;
}
posted @ 2026-03-02 15:10  WinterXorSnow  阅读(15)  评论(0)    收藏  举报