zoukankan      html  css  js  c++  java
  • Luogu P4198 楼房重建 (李超线段树)

    题目

    传送门

    题解

    首先转化成到(0,0)(0,0)的斜率。

    那么就是求多少个点是前缀最大值。

    做法是线段树,用gao(i,x)gao(i,x)表示在ii区间内,之前最大值为xx的答案。
    在这里插入图片描述

    然后发现gao(pr,plmax)gao(p o r,p o l o max)就是gao(p,0)gao(pl,0)gao(p,0)-gao(p o l,0),所以直接用数组存一下gao(i,0)gao(i,0)。代码极短,30行。

    CODE

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 100005;
    int n, m, ans[MAXN<<2];
    double mx[MAXN<<2];
    int query(int i, int l, int r, double v) {
    	if(l == r) return mx[i] > v;
    	if(mx[i] <= v) return 0;
    	int mid = (l + r) >> 1;
    	if(mx[i<<1] <= v) return query(i<<1|1, mid+1, r, v);
    	return query(i<<1, l, mid, v) + ans[i]-ans[i<<1];
    }
    void mdf(int i, int l, int r, int x, double v) {
    	if(l == r) { mx[i] = v; ans[i] = 1; return; }
    	int mid = (l + r) >> 1;
    	if(x <= mid) mdf(i<<1, l, mid, x, v);
    	else mdf(i<<1|1, mid+1, r, x, v);
    	mx[i] = max(mx[i<<1], mx[i<<1|1]);
    	ans[i] = ans[i<<1] + query(i<<1|1, mid+1, r, mx[i<<1]);
    }
    int main () {
    	scanf("%d%d", &n, &m);
    	int x, y;
    	while(m--) {
    		scanf("%d%d", &x, &y);
    		mdf(1, 1, n, x, 1.0*y/x);
    		printf("%d
    ", ans[1]);
    	}
    }
    
  • 相关阅读:
    [每日一题]石子合并 -- 区间DP
    [每日一题]: 最长上升子序列 AND 最长不上升子序列
    [每日一题]:最大子矩阵和
    入门DP--最大子段和
    [转载]:正确的提问方式
    springmvc.xml
    service层springservice.xml文件
    aop切面配置
    配置事务通知
    短信验证
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039190.html
Copyright © 2011-2022 走看看