讲个笑话,数据结构压轴题96行写完。
由于没有标算,我也不知道出题人的实现写了多长。。。
题解:
按照下发的题解模拟即可
我记得区间的LIS是不能直接做的,如果能的话,这道题就没什么难度了。。。
但是这道题有两个限制:新加入的 h ≤ 10 h\leq 10 h≤10,删除的数的位置 ≤ 10 \leq 10 ≤10
也就是说,随着树木的增长,比当前加入的 h h h小的最多只有 10 10 10个。
这启示我们使用暴力。
设 f i f_i fi表示以 i i i开头的LIS长度。
考虑怎么更新,显然需要满足两个条件,在 i i i后面,且比 i i i高。
对于插入,由于高度比当前小的只有不超过 10 10 10个,直接开一个数据结构以位置为下标维护答案,每次暴力将这十个删除,现在能够保证数据结构里面只有高度比当前元素高的,直接按照位置询问即可,再一个个插回去。
对于删除,由于位置在当前这个之前的只有不超过 10 10 10个,直接开一个数据结构以高度为下标维护答案,与上面同理每次暴力将这十个删除再一个个插回去。
发现我们对于数据结构的操作是单点修改,区间询问max,上ZKW线段树。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;T num;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
struct SGT{
static cs int N=1<<18|1;
int a[N],M;
inline void init(int n){for(M=1;M<=n+1;M<<=1);}
inline void set(int p,int v){for(a[p+=M]=v,p>>=1;p;p>>=1)a[p]=std::max(a[p<<1],a[p<<1|1]);}
inline int query(int l,int r){
int ans=0;
for(l+=M-1,r+=M+1;l^r^1;l>>=1,r>>=1){
if(l&1^1)ans=std::max(ans,a[l^1]);
if(r&1) ans=std::max(ans,a[r^1]);
}
return ans;
}
}S1,S2;
cs int N=1e5+10;
int n,m,Mx;
struct atom{int p,h;};
struct cmp1{bool operator()(cs atom &a,cs atom &b){return a.p<b.p;}};
struct cmp2{bool operator()(cs atom &a,cs atom &b){return a.h<b.h;}};
std::set<atom,cmp1> sp;
std::set<atom,cmp2> sh;
atom st[15];int tot;
inline void ins(){
int p=gi(),h=gi()+m+1;
atom a=(atom){p,h};tot=0;
auto it=sh.insert(a).first;sp.insert(a);
while(true){
st[++tot]=*it;S1.set(it->p,0);
if(it==sh.begin())break;--it;
}
for(int re i=1;i<=tot;++i){
int val=S1.query(st[i].p,n)+1;
S1.set(st[i].p,val);
S2.set(st[i].h,val);
}
}
inline void del(){
int x=gi();tot=0;
auto it=sp.begin();
while(--x)st[++tot]=*it++;
S1.set(it->p,0);S2.set(it->h,0);
sh.erase(*it),sp.erase(it);
for(int re i=tot;i;--i)S2.set(st[i].h,0);
for(int re i=tot;i;--i){
int val=S2.query(st[i].h,Mx)+1;
S1.set(st[i].p,val);
S2.set(st[i].h,val);
}
}
signed main(){
#ifdef zxyoi
freopen("lis.in","r",stdin);
#endif
n=gi(),m=gi();S1.init(n),S2.init(Mx=m+20);
while(m--){
switch(gi()){
case 1:ins();break;
case 2:del();break;
}
cout<<S1.a[1]<<"\n";
}
return 0;
}