【校内模拟】lis(线段树)(暴力)

匿名 (未验证) 提交于 2019-12-03 00:11:01

讲个笑话,数据结构压轴题96行写完。

由于没有标算,我也不知道出题人的实现写了多长。。。

题解:

按照下发的题解模拟即可

我记得区间的LIS是不能直接做的,如果能的话,这道题就没什么难度了。。。

但是这道题有两个限制:新加入的h10h\leq 10,删除的数的位置10\leq 10

也就是说,随着树木的增长,比当前加入的hh小的最多只有1010个。

这启示我们使用暴力。

fif_i表示以ii开头的LIS长度。

考虑怎么更新,显然需要满足两个条件,在ii后面,且比ii高。

对于插入,由于高度比当前小的只有不超过1010个,直接开一个数据结构以位置为下标维护答案,每次暴力将这十个删除再一个个插回去。

对于删除,由于位置在当前这个之前的只有不超过1010个,直接开一个数据结构以高度为下标维护答案,每次暴力将这十个删除再一个个插回去。

发现我们对于数据结构的操作是单点修改,区间询问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; } 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!