zoukankan      html  css  js  c++  java
  • 「JSOI2016」灯塔(数论分块+ST做RMQ或单调栈)

    https://loj.ac/problem/2074

    我看到这个题的第一反应是做单调栈:
    (p[i]>=h[j]+sqrt{|i-j|}-h[i])

    (sqrt)这函数吧,也是单调的,性质应该和直线差不多,所以单调队列维护交点单调的若干条曲线。

    求交点可以用二分求,时间复杂度是(O(n~log~n))

    有理有据的做法是分块。

    考虑(sqrt{|i-j|})只有(2sqrt n)种取值,且对于每个每个取值,合法的(j)在一个区间里,预处理(ST)表以快速查询区间最大值最小值。

    时间复杂度:(O(nsqrt n + n~log~n))

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int N = 1e5 + 5;
    
    int n, h[N];
    
    struct P {
    	ll x, y;
    };
    
    #define db long double
    
    ll jd(P a, P b) {
    	ll as = 1e18;
    	for(ll l = b.x, r = 1e18; l <= r; ) {
    		ll m = l + r >> 1;
    		db v1 = a.y + sqrt(m - a.x), v2 = b.y + sqrt(m - b.x);
    		if(v1 < v2) as = m, r = m - 1; else l = m + 1;
    	}
    	return as;
    }
    
    ll jd2(P a, P b) {
    	ll as = -1e18;
    	for(ll l = -1e18, r = b.x; l <= r; ) {
    		ll m = l + r >> 1;
    		db v1 = a.y + sqrt(a.x - m), v2 = b.y + sqrt(b.x - m);
    		if(v1 < v2) as = m, l = m + 1; else r = m - 1;
    	}
    	return as;
    }
    
    P z[N]; int st, en;
    
    ll p[N];
    
    int main() {
    	scanf("%d", &n);
    	fo(i, 1, n) scanf("%d", &h[i]);
    	st = 1, en = 0;
    	fo(i, 1, n) {
    		while(st < en && i >= jd(z[st], z[st + 1])) st ++;
    		if(st <= en) {
    			p[i] = max(p[i], z[st].y - h[i] + (ll) ceil(sqrt(i - z[st].x)));
    		}
    		if(st <= en && z[en].y >= h[i]) continue;
    		P a = (P) {i, h[i]};
    		while(st < en && jd(z[en - 1], z[en]) > jd(z[en], a)) en --;
    		z[++ en] = a;
    	}
    	st = 1, en = 0;
    	fd(i, n, 1) {
    		while(st < en && i <= jd2(z[st], z[st + 1])) st ++;
    		if(st <= en) {
    			p[i] = max(p[i], z[st].y - h[i] + (ll) ceil(sqrt(z[st].x - i)));
    		}
    		if(st <= en && z[en].y >= h[i]) continue;
    		P a = (P) {i, h[i]};
    		while(st < en && jd2(z[en - 1], z[en]) < jd2(z[en], a)) en --;
    		z[++ en] = a;
    	}
    	fo(i, 1, n) pp("%lld
    ", p[i]);
    }
    ```c
  • 相关阅读:
    day02-html+css
    day01-html+css
    ES6-03 symbol数据类型,代理,遍历的使用
    ES6-02 新增方法及函数新增
    Java创建对象基础与修饰符整理
    python dataframe基于另一列提取对应列值
    Python .seq文件批量转.fas 并根据文件夹与文件名重命名
    Python 批量修改文件夹名称 (os.rename)
    Python 批量修改文件夹名称 (os.rename)
    R mgcv包参数 gam参数
  • 原文地址:https://www.cnblogs.com/coldchair/p/12728520.html
Copyright © 2011-2022 走看看