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;
}

浙公网安备 33010602011771号