洛谷 P11210 强制在线动态二维数点

题目传送门

题目中的点满足 \(y\le x\),那么不妨把每个点看成区间 \([y,x]\)。那么题目相当于要求维护若干个区间,支持修改,以及查询询问区间中区间长度的最小值。

从“区间长度的最小值”入手。显然包含别的区间的区间不能成为答案。排除了这样的区间,剩下区间按左端点升序排序,则右端点也单调不降。找到第一个满足 \(l\le l_p\)\(p\) 和最后一个满足 \(r_q\le r\)\(q\),那么答案即为 \(\min_{i=p}^{q}(r_i-l_i)\)

考虑如何维护。用 std::multiset 维护每个右端点对应的左端点,同时用线段树存储这个右端点对应左端点的最大值 \(mxlp\) 以及区间长度的最小值 \(mnlen\),然后 push_up。查询时,先借助 \(mxlp\) 在线段树上二分求出 \(p\),然后直接查询 \([p,r]\)\(mnlen\)。这样做是考虑了 \([l,r]\) 内的所有区间,且不会超时,所以实际上不用去掉“包含其他区间的区间”。时间复杂度 \(\mathcal{O}(n\log n)\)

点击查看代码
const int N=5e5+8,oo=1e9;
int n,q,y[N],x[N];
multiset<int> mts[N];
struct Segment_Tree{
	int mxlp[N<<2],mnlen[N<<2];
	int ls(int o){
		return o<<1;
	}
	int rs(int o){
		return o<<1|1;
	}
	void push_up(int o){
		mxlp[o]=max(mxlp[ls(o)],mxlp[rs(o)]);
		mnlen[o]=min(mnlen[ls(o)],mnlen[rs(o)]);
	}
	void build(int o,int l,int r){
		mxlp[o]=0;
		mnlen[o]=oo;
		if(l==r){
			if((int)mts[l].size()>0){
				mxlp[o]=*--mts[l].end();
				mnlen[o]=l-mxlp[o];
			}
			return;
		}
		int mid=(l+r)/2;
		build(ls(o),l,mid);
		build(rs(o),mid+1,r);
		push_up(o);
	}
	void modify(int o,int l,int r,int pos){
		if(l==r){
			if((int)mts[l].size()==0){
				mxlp[o]=0;
				mnlen[o]=oo;
			}
			else{
				mxlp[o]=*--mts[l].end();
				mnlen[o]=l-mxlp[o];
			}
			return;
		}
		int mid=(l+r)/2;
		if(pos<=mid)
			modify(ls(o),l,mid,pos);
		else
			modify(rs(o),mid+1,r,pos);
		push_up(o);
	}
	int query_min(int o,int l,int r,int ql,int qr){
		if(qr<ql||r<ql||qr<l||r<l)
			return oo;
		if(ql<=l&&r<=qr)
			return mnlen[o];
		int mid=(l+r)/2,res=oo;
		if(ql<=mid)
			res=min(query_min(ls(o),l,mid,ql,qr),res);
		if(mid+1<=qr)
			res=min(res,query_min(rs(o),mid+1,r,ql,qr));
		return res;
	}
	int binary(int o,int l,int r,int ql,int qr,int p){
		if(r<l||qr<ql||r<ql||qr<l||mxlp[o]<p)
			return -1;
		if(l==r)
			return l;
		int mid=(l+r)/2;
		int res=binary(ls(o),l,mid,ql,qr,p);
		if(res==-1)
			res=binary(rs(o),mid+1,r,ql,qr,p);
		return res;
	}
}smt;
void MAIN(){
	cin>>n>>q;
	for(int i=1;i<=n;i++){
		cin>>x[i]>>y[i];
		mts[x[i]].insert(y[i]);
	}
	smt.build(1,1,n);
	int lastans=0;
	while(q--){
		char opt;
		cin>>opt;
		if(opt=='U'){
			int i,a,b;
			cin>>i>>a>>b;
			i^=lastans,a^=lastans,b^=lastans;
			mts[x[i]].erase(mts[x[i]].find(y[i]));
			smt.modify(1,1,n,x[i]);
			x[i]=a,y[i]=b;
			mts[x[i]].insert(y[i]);
			smt.modify(1,1,n,x[i]);
		}
		else if(opt=='Q'){
			int l,r;
			cin>>l>>r;
			l^=lastans,r^=lastans;
			int pos=smt.binary(1,1,n,l,r,l);
			if(pos==-1)
				lastans=0;
			else
				lastans=smt.query_min(1,1,n,pos,r);
			cout<<lastans<<'\n';
		}
	}
}
posted @ 2024-11-20 18:04  Irotan  阅读(0)  评论(0编辑  收藏  举报