Loading

题解 lg4198 楼房重建--线段树

lg P4198 楼房重建

题意

求一个带修改序列的最大单调上升子序列的长度

题外话

我最开始以为只是一座楼房比另一个楼房高就可以看到,但实际上这是无比错误的.

在图上画画图就可以明白

序列里面是斜率!!!

思路

带了修改,有区间,考虑用线段树来维护

对于一个区间 \(x\) ,我们维护 \(len\)\(maxn\) 分别代表从这个区间开头的最大单调上升子序列长度区间最大值

维护\(maxn\)很简单,所以着重考虑的是\(len\)

对于一个区间 \(x\) ,设其左右区间为 \(lc(x)\) , \(rc(x)\),左区间的 \(len\) 显然可以作为\(len[x]\)的答案组成,接着考虑右区间,若 \(maxn[lc(x)]\leq maxn[rc(x)]\),右区间就没有贡献了

否则对右区间继续考虑,只有 \(maxn[lc(rc(x))]> maxn[lc(x)]\) 右区间的左子区间才会有贡献,此时右区间的右子区间只有在\(maxn[rc(rc(x))]>maxn[lc(rc(x))]\)才会有贡献;当\(maxn[lc(rc(x))]\leq maxn[lc(x)]\),此时右区间的右子区间只有在\(maxn[rc(rc(x))]>maxn[lc(x)]\)才会有贡献,这样可以递归下去直到单点,最后统计贡献.以上稍微想想模拟一下就可以明白了.

但有个问题,对于只有 \(maxn[lc(rc(x))]> maxn[lc(x)]\) 右区间的左子区间才会有贡献,此时右区间的右子区间只有在\(maxn[rc(rc(x))]>maxn[lc(rc(x))]\)才会有贡献这种情况,你会发现两边都要递归,那么上限会是\(O(n)\)!!!.不过不急,思考一下\(len\)的意义,你会发现右区间的右子区间的贡献可以通过\(len[rc(x)]-len[lc(rc(x))]\)算出不是

查询就直接在根节点上查,这样我们就得到了一个\(O(nlog_{2}^{2}n)\)的优秀算法

代码

#include<bits/stdc++.h>
using namespace std;
int const MAXN=1e5+10;
int n,m;
struct SegmentTree{
	#define lc(x) x<<1
	#define rc(x) x<<1|1
	int len[MAXN<<2],l[MAXN<<2],r[MAXN<<2];
	double maxn[MAXN<<3];
	void build(int x,int L,int R){
		l[x]=L,r[x]=R;
		if(L==R)return;
		int mid=(L+R)>>1;
		build(lc(x),L,mid);
		build(rc(x),mid+1,R);
	}
	int find(int x,double h){
		if(l[x]==r[x]){
			if(maxn[x]>h)return 1;
			return 0;
		}
		int sum=0;
		if(maxn[lc(x)]>h){
			sum+=find(lc(x),h)+len[x]-len[lc(x)];
		}else if(maxn[rc(x)]>h){
			sum+=find(rc(x),h);
		}
		return sum;
	}
	void pushup(int x){
		maxn[x]=max(maxn[lc(x)],maxn[rc(x)]);
		len[x]=len[lc(x)];
		if(maxn[rc(x)]>maxn[lc(x)]){
			len[x]+=find(rc(x),maxn[lc(x)]);
		}
		return;
	}
	void insert(int x,int L,int R,int p,int a){
		l[x]=L,r[x]=R;
		if(l[x]==r[x]){maxn[x]=(double)a/(double)p,len[x]=1;return;}
		int mid=(L+R)>>1;
		if(p<=mid)insert(x<<1,L,mid,p,a);
		else insert(x<<1|1,mid+1,R,p,a);
		pushup(x);
	}
}Tree;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		Tree.insert(1,1,n,x,y);
		printf("%d\n",Tree.len[1]);
	}
	return 0;
}
posted @ 2020-10-26 21:56  fpjo  阅读(76)  评论(0编辑  收藏  举报