洛谷 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';
}
}
}