QOJ7980 区间切割

为什么不会呢。

看到这个切割以为是要在 \(mid=\lfloor\frac{l+r+1}{2}\rfloor\) 上做文章,发现需要维护按 \(mid\) 排序,分裂两部分,左半部分按 \(l\) 排序,右半部分按 \(r\) 排序,再并起来。分块后每个块有效操作数是 \(\sqrt{n}\) 的,所以应该是能做到 \(O(n\sqrt n \log n)\)。口胡的所以不能确保正确 /lengh。

因为这个优化显然是困难的,所以不考虑对 \([l,r]\) 层一起处理,这一维可以扫描线解决,考虑对单独一层怎么处理。

如果每次操作都靠近区间 \(mid\),那么复杂度是 \(O(\log m)\) 的。考虑能否用这个性质。将区间均分为三段,则左右两端的修改形如对 \(l\)\(\max\) 或对 \(r\)\(\min\),对中间修改最多有 \(\log m\) 次。线段树维护区间中修改时间的最小值以及对应的修改位置,两种操作都能维护,详见代码。

Takanashi Rikka
#include<bits/stdc++.h>
using namespace std;
#define fin(x) freopen(#x".in","r",stdin)
#define fout(x) freopen(#x".out","w",stdout)
#define fr(x) fin(x),fout(x);
#define Fr(x,y) fin(x),fout(y)
#define INPUT(_1,_2,FILE,...) FILE
#define IO(...) INPUT(__VA_ARGS__,Fr,fr)(__VA_ARGS__)
#define pb push_back
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define intz(x,z) memset((x),(z),sizeof((x)))
#define cfast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
inline ll lowbit(ll x){return x&-x;}
#define fi first
#define se second
inline void cmx(auto &x,ll y){if(y>x)x=y;}
inline void cmn(auto &x,ll y){if(y<x)x=y;}
const int N=1e6+5;
int l[N],r[N];vector<pii>q[N];
struct node{int l,r,x,p;}t[N<<2];
void build(int u,int l,int r){
	t[u]={l,r,(int)1e9,l};if(l==r)return;int mid=l+r>>1;
	build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
inline void pushup(int u){
	t[u].x=min(t[u<<1].x,t[u<<1|1].x);
	t[u].p=t[(u<<1)+(t[u<<1|1].x==t[u].x)].p;
}
void upd(int u,int x,int d){
	if(t[u].l==t[u].r)return t[u].x=d,void();
	int mid=t[u].l+t[u].r>>1;
	upd((x<=mid?u<<1:u<<1|1),x,d),pushup(u);
}
pii query(int u,int l,int r){
	if(l>r)return mp(1e9,0);
	if(t[u].l>=l&&t[u].r<=r)return mp(t[u].x,t[u].p);
	int mid=t[u].l+t[u].r>>1;pii res=mp(1e9,0);
	if(l<=mid)res=min(res,query(u<<1,l,r));
	if(r>mid)res=min(res,query(u<<1|1,l,r));
	return res;
}
int getl(int u,int x,int d){
	if(t[u].l>x||t[u].x>=d)return -1;
	if(t[u].l==t[u].r)return t[u].l;
	int res=-1;
	cmx(res,getl(u<<1|1,x,d));
	if(res>-1)return res;
	return cmx(res,getl(u<<1,x,d)),res;
}
int getr(int u,int x,int d){
	if(t[u].r<x||t[u].x>=d)return 1e9;
	if(t[u].l==t[u].r)return t[u].l;
	int res=1e9;
	cmn(res,getr(u<<1,x,d));
	if(res<1e9)return res;
	return cmn(res,getr(u<<1|1,x,d)),res;
}
void UesugiErii(){
	int n,m,id;cin>>n>>m>>id;build(1,1,m);
	for(int i=1;i<=n;i++)cin>>l[i]>>r[i];
	for(int i=1,x,L,R;i<=m;i++)
		cin>>x>>L>>R,q[L].pb(mp(x,i)),q[R+1].pb(mp(x,-i));
	for(int i=1;i<=n;i++){
		for(pii j:q[i])
			upd(1,j.fi,(j.se>0?j.se:1e9));
		while(1){
			int len=max((r[i]-l[i]+1)/3,1),L=l[i]+len,R=r[i]-len;
			if(r[i]-l[i]==0)break;
			pii res=query(1,L,R);int t=res.fi,p=res.se;
			cmx(l[i],getl(1,L-1,t)),cmn(r[i],getr(1,R+1,t));
			if(t==1e9)break;
			((l[i]+r[i]+1>>1)<=p?r[i]:l[i])=p;
		}
		cout<<l[i]<<' '<<r[i]<<'\n';
	}
}
signed main(){
	cfast;
	int _=1;//cin>>_;
	for(;_;_--)UesugiErii();
	return 0;
}
posted @ 2025-12-21 16:36  Uesugi1  阅读(8)  评论(0)    收藏  举报