问题拆解,好题&难题
发现:每个点经历了一次修改后,若(x_i<x_j)则(y_i>y_j)(貌似并没有用到?)
考虑线段树分治:
每个询问记录修改时间区间
每个时间段的区间将询问的点按(x)或(y)排序
用动态开点线段树维护最大值算出每个修改的区间
例(H)操作,在长度小于(l)的区域,可能会被(V)操作扫走,所以每次(V)操作,将(n-l_v-1)以内的区域都与(l_v)取(max),这样就可以把两种操作分开进行,修改答案
加入点无影响
时间复杂度(O(nlog_n^2))
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f==1?x:-x;
}
#define pai pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define vi vector<int>
const int N=1600004;
int n,m,Q,qn,tim,tot;
int a[N][3],b[N][3],c[N][2],ans[N][2];
int t[N<<5],lc[N<<5],rc[N<<5],rt[2];
vector<pai>mv[2];
inline int newnode(){
++tot;
lc[tot]=rc[tot]=t[tot]=0;
return tot;
}
void modify(int &p,int l,int r,int ql,int qr,int k){
if(ql>qr||qr<0||ql>n)return;
if(!p)p=newnode();
if(ql<=l&&r<=qr){t[p]=max(t[p],k);return;}
int mid=l+r>>1;
if(ql<=mid)modify(lc[p],l,mid,ql,qr,k);
if(mid<qr)modify(rc[p],mid+1,r,ql,qr,k);
}
int query(int p,int l,int r,int x){
if(!p)return 0;
if(l==r)return t[p];
int mid=l+r>>1;
if(x<=mid)return max(t[p],query(lc[p],l,mid,x));
else return max(t[p],query(rc[p],mid+1,r,x));
}
inline void mdf(int op,int len){//找每次操作可以修改的区域
int t=query(rt[op^1],0,n,len);
mv[op].pb(mp(len,t));
modify(rt[op],0,n,t,n-len-1,len+1);
}
inline bool cmp0(int x,int y){
return ans[x][1]>ans[y][1];
}
inline bool cmp1(int x,int y){
return ans[x][0]>ans[y][0];
}
inline void solve(int l,int r,vi w){
if(l>r)return;
vi lw,rw,tmp;
int mid=l+r>>1,ql,qr,j,x,y;
for(auto i:w){
ql=b[i][1];qr=b[i][2];
if(ql<=l&&r<=qr)tmp.pb(i);
else{
if(ql<=mid)lw.pb(i);
if(mid<qr)rw.pb(i);
}
}
rt[0]=rt[1]=tot=0;
mv[0].clear();mv[1].clear();
for(int i=l;i<=r;i++)mdf(c[i][0],c[i][1]);
sort(tmp.begin(),tmp.end(),cmp0);
sort(mv[0].begin(),mv[0].end(),greater<pai>());
rt[0]=tot=j=0;
for(auto i:tmp){
x=ans[i][0];y=ans[i][1];
for(;j<mv[0].size()&&mv[0][j].fi>=y;j++){
modify(rt[0],0,n,mv[0][j].se,n-mv[0][j].fi,n-mv[0][j].fi);
}
ans[i][0]=max(x,query(rt[0],0,n,x));
}
sort(tmp.begin(),tmp.end(),cmp1);
sort(mv[1].begin(),mv[1].end(),greater<pai>());
rt[1]=tot=j=0;
for(auto i:tmp){
x=ans[i][0];y=ans[i][1];
for(;j<mv[1].size()&&mv[1][j].fi>=x;j++){
modify(rt[1],0,n,mv[1][j].se,n-mv[1][j].fi,n-mv[1][j].fi);
}
ans[i][1]=max(y,query(rt[1],0,n,y));
}
if(l==r)return;
solve(l,mid,lw);solve(mid+1,r,rw);
}
int main(){
n=read();m=read();Q=read();
for(int i=1;i<=m;i++){
a[i][0]=read();a[i][1]=read();
a[i][2]=1;
}
for(int i=1,op,x;i<=Q;i++){
op=read();
if(op==1){
b[++qn][0]=x=read();b[qn][1]=a[x][2];
b[qn][2]=tim;
}
else if(op==2){
c[++tim][1]=read();
}
else if(op==3){
c[++tim][0]=1;c[tim][1]=read();
}
else{
a[++m][0]=read();a[m][1]=read();
a[m][2]=tim+1;
}
}
vi vec;
for(int i=1,x;i<=qn;i++){
x=b[i][0];
ans[i][0]=a[x][0];ans[i][1]=a[x][1];
if(b[i][1]<=b[i][2])vec.pb(i);
}
solve(1,tim,vec);
for(int i=1;i<=qn;i++)
cout<<ans[i][0]<<" "<<ans[i][1]<<"
";
return (0-0);
}