zoukankan      html  css  js  c++  java
  • 「JOISC 2019 Day2」两个天线(线段树)

    https://loj.ac/problem/3033

    题解:

    这题的线段树维护有点妙。

    (|h[i]-h[j]|=max(h[i]-h[j],h[j]-h[i])),所以作两遍就不用考虑绝对值了,考虑现在是(h[j]-h[i])

    用线段树维护每个位置的标记, 每个位置的标记有(p[x]、q[x]).

    考虑对于(i,j),首先(jin[i+a[i],i+b[i]]),那么从左往右枚举(j)的时候,在(i+a[i])处开启(i)处的标记((p[i]=-h[i]))(i+b[i]+1)处关闭((p[i]=-inf))

    还得满足(iin[j-b[j],j-a[j]]),那么在到(j)时,对那一个区间的(q)都和(h[j])(max)

    一个查询就是询问一个区间的历史版本的(p[i]+q[i])的最大值,这个很简单。

    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 = 2e5 + 5;
    
    const int inf = 1e9;
    
    int n, Q, h[N], a[N], b[N];
    struct ask {
    	int l, r;
    } c[N];
    
    vector<int> q[N];
    #define pb push_back
    
    vector<int> p[N];
    
    void Init() {
    	scanf("%d", &n);
    	fo(i, 1, n) {
    		scanf("%d %d %d", &h[i], &a[i], &b[i]);
    		if(i + a[i] <= n) p[i + a[i]].pb(i);
    		if(i + b[i] + 1 <= n) p[i + b[i] + 1].pb(i);
    	}
    	scanf("%d", &Q);
    	fo(i, 1, Q) {
    		scanf("%d %d", &c[i].l, &c[i].r);
    		q[c[i].r].pb(i);
    	}  
    }
    
    #define i0 i + i
    #define i1 i + i + 1
    int mx[N * 4], t[N * 4], lz[N * 4];
    int pl, pr, px;
    void qmax(int i, int x) {
    	lz[i] = max(lz[i], x);
    	t[i] = max(t[i], mx[i] + lz[i]);
    }
    void down(int i) {
    	if(lz[i] > -inf) {
    		qmax(i0, lz[i]);
    		qmax(i1, lz[i]);
    		lz[i] = -inf;
    	}
    }
    void add(int i, int x, int y) {
    	if(y < pl || x > pr) return;
    	if(x == y) {
    		lz[i] = -inf; mx[i] = px;
    		return;
    	}
    	int m = x + y >> 1; down(i);
    	add(i0, x, m); add(i1, m + 1, y);
    	t[i] = max(t[i0], t[i1]);
    	mx[i] = max(mx[i0], mx[i1]);
    }
    void xiu(int i, int x, int y) {
    	if(y < pl || x > pr) return;
    	if(x >= pl && y <= pr) {
    		qmax(i, px);
    		return;
    	}
    	int m = x + y >> 1; down(i);
    	xiu(i0, x, m); xiu(i1, m + 1, y);
    	t[i] = max(t[i0], t[i1]);
    }
    void ft(int i, int x, int y) {
    	if(y < pl || x > pr) return;
    	if(x >= pl && y <= pr) {
    		px = max(px, t[i]);
    		return;
    	}
    	int m = x + y >> 1; down(i);
    	ft(i0, x, m); ft(i1, m + 1, y);
    }
    
    int ans[N], us[N];
    
    void work() {
    	fo(i, 1, n * 4)	{
    		t[i] = mx[i] = lz[i] = -inf;
    	}
    	fo(i, 1, n) us[i] = 0;
    	fo(i, 1, n) {
    		ff(j, 0, p[i].size()) {
    			int x = p[i][j];
    			pl = pr = x; px = us[x] ? -inf : -h[x];
    			add(1, 1, n);
    			us[x] = 1;
    		}
    		pl = i - b[i], pr = i - a[i]; px = h[i];
    		xiu(1, 1, n);
    		ff(j, 0, q[i].size()) {
    			int x = q[i][j];
    			pl = c[x].l, pr = c[x].r, px = -2 * inf;
    			ft(1, 1, n);
    			ans[x] = max(ans[x], px);
    		}
    	}
    }
    
    int main() {
    	Init();
    	fo(i, 1, Q) ans[i] = -inf;
    	work();
    	fo(i, 1, n) h[i] = inf - h[i];
    	work();
    	fo(i, 1, Q) pp("%d
    ", ans[i] < 0 ? -1 : ans[i]);
    }
    
  • 相关阅读:
    Mac 配置自定义执行文件 pull.sh,push.sh
    vue-element-admin列表管理
    使用elementui图标
    Mac brew 启动php
    VUE , 表单中如何用获取接口数据的select
    Mac 如何关闭PHPstorm,双击shift快捷键
    spectacle 很好用的应用分屏工具Mac
    面对灵活的配置如何建表,使用json
    mac 下灵活管理node版本
    Node Sass version 6.0.0 is incompatible with^4.0.0
  • 原文地址:https://www.cnblogs.com/coldchair/p/12410476.html
Copyright © 2011-2022 走看看