zoukankan      html  css  js  c++  java
  • 「JOI Open 2019」三级跳(找性质缩状态+线段树)

    https://loj.ac/problem/3153

    题解:

    若有(a[i]、a[j](i<j)),若存在(mid)满足(i<mid<j,a[mid]>=a[i],a[j]),则(a[i]、a[mid])作为前两个一定更优。

    那么,所以有用的(a[i]、a[j])便缩减到了(O(n))个,具体为每个数和它左边第一个比他的大的数形成的对+每个数和它右边第一个大于等于它的数形成的对。

    可以用栈找出这(O(n))对有用的。

    接着,对于询问,按l从大到小排序,在求解的同时加入有用的对。

    现在问题变成了,有(n)个标记(c[1..n]),一开始全0,每次使(c[x..n])对一个数取max,或者查询一个区间的(c[i]+a[i])的最大值。

    由于查询也是求区间max,所以不用吉利线段树(或者什么单调栈),普通lazytag线段树就可以做了。

    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 = 5e5 + 5;
    
    int n, a[N], Q;
    struct ask {
    	int l, r;
    } b[N];
    
    vector<int> q[N];
    #define pb push_back
    
    void Init() {
    	scanf("%d", &n);
    	fo(i, 1, n) scanf("%d", &a[i]);
    	scanf("%d", &Q);
    	fo(i, 1, Q) scanf("%d %d", &b[i].l, &b[i].r), q[b[i].l].pb(i);
    }
    
    #define i0 i + i
    #define i1 i + i + 1
    int t[N * 4], mx[N * 4], lz[N * 4];
    int pl, pr, px;
    
    void bt(int i, int x, int y) {
    	if(x == y) { mx[i] = t[i] = a[x]; return;}
    	int m = x + y >> 1;
    	bt(i0, x, m); bt(i1, m + 1, y);
    	mx[i] = t[i] = max(t[i0], t[i1]);
    }
    void qmax(int i, int v) {
    	lz[i] = max(lz[i], v);
    	t[i] = max(t[i], v + mx[i]);
    }
    void down(int i) {
    	if(lz[i]) {
    		qmax(i0, lz[i]);
    		qmax(i1, lz[i]);
    		lz[i] = 0;
    	}
    }
    void add(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);
    	add(i0, x, m); add(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 z[N], z0;
    
    int ans[N];
    
    vector<int> p[N];
    
    void build() {
    	bt(1, 1, n);
    	fo(i, 1, n) {
    		while(z0 > 0 && a[i] > a[z[z0]]) {
    			p[z[z0]].pb(i);
    			z0 --;
    		}
    		z[++ z0] = i;
    	}
    	z0 = 0;
    	fd(i, n, 1)	{
    		while(z0 > 0 && a[i] >= a[z[z0]]) {
    			int j = z[z0];
    			pl = 2 * j - i, pr = n; px = a[i] + a[j];
    			add(1, 1, n);
    			z0 --;
    		}
    		z[++ z0] = i;
    		ff(k, 0, p[i].size()) {
    			int j = p[i][k];
    			pl = 2 * j - i, pr = n; px = a[i] + a[j];
    			add(1, 1, n);
    		}
    		ff(j, 0, q[i].size()) {
    			int x = q[i][j];
    			pl = i; pr = b[x].r; px = 0;
    			ft(1, 1, n);
    			ans[x] = px;
    		}
    	}
    	fo(i, 1, Q) pp("%d
    ", ans[i]);
    }
    
    int main() {
    	Init();
    	build();
    }
    
    
  • 相关阅读:
    Go网络文件传输
    Go网络编程
    LNMP环境搭建(PHP7.4.0)
    LNMP环境搭建(PHP7.2.25)
    Please ensure the argon2 header and library are installed
    MySQL权限管理
    nginx ingress controller配置默认SSL证书
    kubernetes pod内抓包,telnet检查网络连接的几种方式
    ansible取出register变量中最长字符串
    kubernetes flannel pod CrashLoopBackoff解决
  • 原文地址:https://www.cnblogs.com/coldchair/p/12386665.html
Copyright © 2011-2022 走看看