讲个笑话,数据结构压轴题96行写完。
由于没有标算,我也不知道出题人的实现写了多长。。。
题解:
按照下发的题解模拟即可
我记得区间的LIS是不能直接做的,如果能的话,这道题就没什么难度了。。。
但是这道题有两个限制:新加入的,删除的数的位置
也就是说,随着树木的增长,比当前加入的小的最多只有个。
这启示我们使用暴力。
设表示以开头的LIS长度。
考虑怎么更新,显然需要满足两个条件,在后面,且比高。
对于插入,由于高度比当前小的只有不超过个,直接开一个数据结构以位置为下标维护答案,每次暴力将这十个删除再一个个插回去。
对于删除,由于位置在当前这个之前的只有不超过个,直接开一个数据结构以高度为下标维护答案,每次暴力将这十个删除再一个个插回去。
发现我们对于数据结构的操作是单点修改,区间询问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; }
来源:51CTO
作者:zxyoi_dreamer
链接:https://blog.csdn.net/zxyoi_dreamer/article/details/101194008