[loj3273]扫除
对所有23操作建立一个序列,问题即求一个点经过一段连续操作后的结果
建立线段树并将询问离线,考虑线段树上每一个节点,即是没有1操作且4操作均在末尾的子问题
(保证操作总数为$o(q\log q)$,即区间长度+拆分到此区间的询问数)
对于第$i$个操作,记$p_{i}\in \{0,1\}$为操作类型(分别指H和V操作)$,l_{i}$为操作参数
结论:记$L_{i}=\max_{1\le j<i,p_{i}\ne p_{j},L_{j}\le l_{i}<n-l_{j}}l_{j}+1$,则第$i$个操作被执行当且仅当(初始)$\begin{cases}y\le l_{i},x\ge L_{i}&p_{i}=0\\x\le l_{i},y\ge L_{i}&p_{i}=1\end{cases}$
关于操作执行的定义,具体如下(以$p_{i}=0$的情况为例):
(将操作时)称$y>l_{i}$的操作不执行,称$y\le l_{i}$且$x<n-l_{j}$的操作被执行,其余操作是否执行均可
对其归纳证明,根据对称性,不妨仅考虑$p_{i}=0$的情况($p_{i}=1$时类似)
充分性:若$y\le l_{i},x\ge L_{i}$,根据归纳假设,之前会使得$y>l_{i}$的操作均不执行,进而最终$y\le l_{i}$
必要性:反证法,假设第$i$个操作被执行但不满足$x\ge L_{i}$($y\le l_{i}$显然满足)
根据$L_{i}$的定义,即存在$1\le j<i$满足$p_{j}=1,L_{j}\le l_{i}<n-l_{j},x\le l_{j}$
显然第$j$个操作不能被执行,即该时刻必然有$x>l_{j}>n-l_{i}$,那么第$i
通过线段树$o(q\log n)$得到$L_{i}$,进而根据上述结论类似的$o(q\log n)$求出结果
时间复杂度为$o(q\log q\log n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000005 4 #define pii pair<int,int> 5 #define fi first 6 #define se second 7 #define L (k<<1) 8 #define R (L+1) 9 #define mid (l+r>>1) 10 vector<int>v[N<<2]; 11 int n,m,t,q,k,p,num[11],T[N],id[N],f[N]; 12 pii P[N<<1],Q[N],a[N],ans[N]; 13 int read(){ 14 int x=0; 15 char c=getchar(); 16 while ((c<'0')||(c>'9'))c=getchar(); 17 while ((c>='0')&&(c<='9')){ 18 x=x*10+c-'0'; 19 c=getchar(); 20 } 21 return x; 22 } 23 void write(int x,char c='\0'){ 24 while (x){ 25 num[++num[0]]=x%10; 26 x/=10; 27 } 28 if (!num[0])putchar('0'); 29 while (num[0])putchar(num[num[0]--]+'0'); 30 putchar(c); 31 } 32 struct Tree{ 33 int V,rt,ls[N*50],rs[N*50],mx[N*50]; 34 void init(){ 35 V=rt=0; 36 } 37 int New(){ 38 int k=++V; 39 ls[k]=rs[k]=mx[k]=0; 40 return k; 41 } 42 void update(int &k,int l,int r,int x,int y,int z){ 43 if ((l>y)||(x>r))return; 44 if (!k)k=New(); 45 if ((x<=l)&&(r<=y)){ 46 mx[k]=max(mx[k],z); 47 return; 48 } 49 update(ls[k],l,mid,x,y,z); 50 update(rs[k],mid+1,r,x,y,z); 51 } 52 int query(int k,int l,int r,int x){ 53 if (!k)return 0; 54 if (l==r)return mx[k]; 55 if (x<=mid)return max(query(ls[k],l,mid,x),mx[k]); 56 return max(query(rs[k],mid+1,r,x),mx[k]); 57 } 58 void update(int x,int y,int z){ 59 update(rt,0,n,x,y,z); 60 } 61 int query(int k){ 62 return query(rt,0,n,k); 63 } 64 }F[2]; 65 bool cmp(int x,int y){ 66 return f[x]<f[y]; 67 } 68 bool cmpx(int x,int y){ 69 return ans[x].fi<ans[y].fi; 70 } 71 bool cmpy(int x,int y){ 72 return ans[x].se<ans[y].se; 73 } 74 void add(int k,int l,int r,int x,int y,int z){ 75 if ((l>y)||(x>r))return; 76 if ((x<=l)&&(r<=y))v[k].push_back(z); 77 else add(L,l,mid,x,y,z),add(R,mid+1,r,x,y,z); 78 } 79 void dfs(int k,int l,int r){ 80 F[0].init(),F[1].init(); 81 for(int i=l;i<=r;i++){ 82 f[i]=F[a[i].fi^1].query(a[i].se); 83 F[a[i].fi].update(f[i],n-a[i].se-1,a[i].se+1); 84 } 85 F[0].init(),F[1].init(); 86 id[0]=0; 87 for(int i=l;i<=r;i++) 88 if (!a[i].fi)id[++id[0]]=i; 89 sort(id+1,id+id[0]+1,cmp); 90 sort(v[k].begin(),v[k].end(),cmpx); 91 for(int i=0,j=1;i<v[k].size();i++){ 92 int Id=v[k][i]; 93 while ((j<=id[0])&&(f[id[j]]<=ans[Id].fi)){ 94 F[0].update(0,a[id[j]].se,n-a[id[j]].se); 95 j++; 96 } 97 ans[Id].fi=max(ans[Id].fi,F[0].query(ans[Id].se)); 98 } 99 id[0]=0; 100 for(int i=l;i<=r;i++) 101 if (a[i].fi)id[++id[0]]=i; 102 sort(id+1,id+id[0]+1,cmp); 103 sort(v[k].begin(),v[k].end(),cmpy); 104 for(int i=0,j=1;i<v[k].size();i++){ 105 int Id=v[k][i]; 106 while ((j<=id[0])&&(f[id[j]]<=ans[Id].se)){ 107 F[1].update(0,a[id[j]].se,n-a[id[j]].se); 108 j++; 109 } 110 ans[Id].se=max(ans[Id].se,F[1].query(ans[Id].fi)); 111 } 112 if (l>=r)return; 113 dfs(L,l,mid),dfs(R,mid+1,r); 114 } 115 int main(){ 116 n=read(),k=read(),m=read(); 117 for(int i=1;i<=k;i++)P[i].fi=read(),P[i].se=read(); 118 for(int i=1;i<=m;i++){ 119 p=read(); 120 if (p==1)Q[++q]=make_pair(read(),t); 121 if ((p==2)||(p==3))a[++t]=make_pair(p-2,read()); 122 if (p==4)P[++k].fi=read(),P[k].se=read(),T[k]=t; 123 } 124 for(int i=1;i<=q;i++){ 125 ans[i]=P[Q[i].fi]; 126 add(1,1,t,T[Q[i].fi]+1,Q[i].se,i); 127 } 128 dfs(1,1,t); 129 for(int i=1;i<=q;i++)write(ans[i].fi,' '),write(ans[i].se,'\n'); 130 return 0; 131 }