lgP4198 楼房重建

好菜啊,大原题都没做过

题意转换,相当于是 每次 单点修改后 求\(p[i] / i\)的单调递增子序列的最长长度

之后就不是很会了。。。。

参阅题解之后,相当于是 把\(push\_up\)的操作变复杂一点 加强它

然后就可以很快的实现单点修改 + 固定一个端点的 单调递增子序列的最大长度

代码实现也很简单

#include<bits/stdc++.h>
#define MAXN 100005
#define INF 0x3f3f3f3f
using namespace std;

int n,m;

struct node{
	int ans;
	double mx;
}t[MAXN * 5];

int que(int rt , int l , int r , double v){
	if(l == r)return t[rt].mx > v;
	int mid = (l + r) >> 1;
	if(t[rt << 1].mx <= v)return que(rt << 1 | 1 , mid + 1 , r , v);
	else return que(rt << 1 , l , mid , v) + t[rt].ans - t[rt << 1].ans;
}

void update(int rt , int l , int r , int x , double v){
	if(l == r){
		t[rt].mx = v;
		t[rt].ans = 1;
		return;
	}
	int mid = (l + r) >> 1;
	if(x <= mid)update(rt << 1 , l , mid , x , v);
	else update(rt << 1 | 1 , mid + 1 , r , x , v);
	t[rt].mx = max(t[rt << 1].mx , t[rt << 1 | 1].mx);
	t[rt].ans = t[rt << 1].ans + que(rt << 1 | 1 , mid + 1 , r , t[rt << 1].mx);
}


int main(){
	scanf("%d%d" , &n , &m);
	int x,y;
	for(int i = 1 ; i <= m ; i++){
		cin>>x>>y;
		update(1 , 1 , 1e5 , x , (y * 1.0) / (x * 1.0));
		cout<<t[1].ans<<endl;
	}
	
	
}
上一篇:剑指Offer 68-II.二叉树的最近公共祖先


下一篇:练习:二叉树的最小深度