zoukankan      html  css  js  c++  java
  • 【LG2839】[国家集训队]middle

    【LG2839】[国家集训队]middle

    题面

    洛谷

    题解

    按照求中位数的套路,我们二分答案(mid),将大于等于(mid)的数设为(1),否则为(-1)

    若一个区间和大于等于(0),则答案可以更大,反之亦然。

    对于这个题,我们只要维护出([b+1,c-1])之间二分答案后的和,([a,b])的最大右段和,([c,d])的最大左段和,判断这三项加起来是否大于零即可。

    我们维护这三项和的话,按照权值为前缀,建主席树就行了。

    代码

    #include <iostream> 
    #include <cstdio> 
    #include <cstdlib> 
    #include <cstring> 
    #include <cmath> 
    #include <algorithm> 
    using namespace std;
    inline int gi() {
        register int data = 0, w = 1; 
        register char ch = 0; 
        while (!isdigit(ch) && ch != '-') ch = getchar(); 
        if (ch == '-') w = -1, ch = getchar(); 
        while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
        return w * data; 
    } 
    const int MAX_N = 2e4 + 5; 
    struct Info { 
    	int lmax, rmax, sum;
    	Info () {lmax = rmax = -1, sum = 0; } 
    	Info (int lmax, int rmax, int sum) : lmax(lmax), rmax(rmax), sum(sum) { } 
    } ; 
    Info operator + (Info l, Info r) { 
    	Info res; 
    	res.lmax = max(l.lmax, l.sum + r.lmax); 
    	res.rmax = max(r.rmax, r.sum + l.rmax);
    	res.sum = l.sum + r.sum; 
    	return res; 
    } 
    struct Node { int ls, rs; Info v; } t[MAX_N * 20]; 
    int rt[MAX_N], tot = 0; 
    void build(int &o, int l, int r) { 
    	o = ++tot; 
    	t[o].v = (Info){r - l + 1, r - l + 1, r - l + 1}; 
    	if (l == r) return ;
    	int mid = (l + r) >> 1; 
    	build(t[o].ls, l, mid);
    	build(t[o].rs, mid + 1, r); 
    } 
    void insert(int &o, int p, int l, int r, int pos) { 
    	o = ++tot, t[o] = t[p]; 
    	if (l == r) return (void)(t[o].v = (Info){-1, -1, -1}); 
    	int mid = (l + r) >> 1; 
    	if (pos <= mid) insert(t[o].ls, t[p].ls, l, mid, pos); 
    	else insert(t[o].rs, t[p].rs, mid + 1, r, pos); 
    	t[o].v = t[t[o].ls].v + t[t[o].rs].v; 
    } 
    Info query(int o, int l, int r, int ql, int qr) { 
    	if (ql <= l && r <= qr) return t[o].v; 
    	int mid = (l + r) >> 1; Info res; 
    	if (ql <= mid) res = res + query(t[o].ls, l, mid, ql, qr);
    	if (qr > mid) res = res + query(t[o].rs, mid + 1, r, ql, qr); 
    	return res; 
    } 
    int N, id[MAX_N], a[MAX_N], q[5]; 
    bool check(int mid) { 
    	int val = 0; 
    	if (q[1] + 1 <= q[2] - 1) val += query(rt[mid], 1, N, q[1] + 1, q[2] - 1).sum; 
    	val += query(rt[mid], 1, N, q[0], q[1]).rmax; 
    	val += query(rt[mid], 1, N, q[2], q[3]).lmax; 
    	return val >= 0; 
    } 
    bool cmp(const int &x, const int &y) { return a[x] < a[y]; } 
    int main() { 
    #ifndef ONLINE_JUDGE 
    	freopen("cpp.in", "r", stdin); 
    #endif 
    	N = gi(); build(rt[1], 1, N); 
    	for (int i = 1; i <= N; i++) a[i] = gi(), id[i] = i; 
    	sort(&id[1], &id[N + 1], cmp); 
    	for (int i = 2; i <= N; i++) insert(rt[i], rt[i - 1], 1, N, id[i - 1]); 
    	for (int Q = gi(), ans = 0; Q--; ) { 
    		for (int i = 0; i < 4; i++) q[i] = (gi() + ans) % N + 1;
    		sort(&q[0], &q[4]);
    		int l = 1, r = N;
    		while (l <= r) {
    			int mid = (l + r) >> 1; 
    			if (check(mid)) ans = a[id[mid]], l = mid + 1;
    			else r = mid - 1; 
    		} 
    		printf("%d
    ", ans); 
    	} 
        return 0;
    }
    
  • 相关阅读:
    Qt之使用CQU库快速开发统一风格界面
    Springboot中使用redis进行api防刷限流
    SpringBoot使用拦截器、过滤器、监听器
    ElasticSearch中文分词器-IK分词器的使用
    里式替换原则——面向对象程序设计原则
    使用Spring中的PropertyPlaceholderConfigurer读取文件
    新版本SpringCloud sleuth整合zipkin
    解放双手,在PC端进行Android真机调试
    破解Android设备无法联调的谜题
    打python&adb组合拳,实现微信读书永久免费读
  • 原文地址:https://www.cnblogs.com/heyujun/p/11695299.html
Copyright © 2011-2022 走看看