zoukankan      html  css  js  c++  java
  • SP1043 GSS1

    题目传送门:SP1043 GSS1 - Can you answer these queries I

    静态维护子段和最大值

    提供结构体指针线段树写法:

    (l)为区间左端点, (r)为区间右端点;

    (ls)为以(l)为左端点的最大子段和, (rs)为以(r)为右端点的最大子段和;

    (sum)为区间和, (val)为区间子段和最大和。

    (ch[0])为左儿子, (ch[1])为右儿子.

    考虑维护:

    o->sum = ch[0]->sum + ch[1]->sum;
    o->ls = max(ch[0]->ls, ch[0]->sum + ch[1]->ls);
    o->rs = max(ch[1]->rs, ch[1]->sum + ch[0]->rs);
    o->val = max(max(ch[0]->val, ch[1]->val), max(max(o->ls, o->rs), ch[0]->rs + ch[1]->ls);

    这样可以考虑到所有的转移情况;

    在询问时, 若询问区间跨过左右两个子区间, 则我们利用(ls, rs, sum)来更新出当前区间的(val);

    所以我们返回结构体指针。

    code:

    #include <iostream>
    #include <cstdio>
    using namespace std;
    const int N = 5e4 + 5;
    int read() {
    	int x = 0, f = 1; char ch;
    	while(! isdigit(ch = getchar())) (ch == '-') && (f = -f);
    	for(x = ch^48; isdigit(ch = getchar()); x = (x<<3) + (x<<1) + (ch^48));
    	return x * f;
    }
    int n, m;
    template <class T> T Max(T a, T b) { return a > b ? a : b; }
    struct Segment {
    	struct node {
    		int l, r, ls, rs, sum, val;
    		node *ch[2];
    		node(int l, int r, int ls, int rs, int sum, int val) : l(l), r(r), ls(ls), rs(rs), sum(sum), val(val) {
    			ch[0] = ch[1] = NULL;
    		}
    		inline int mid() { return (l + r) >> 1; }
    		inline void up() {
    			sum = ch[0]->sum + ch[1]->sum;
    			ls = Max(ch[0]->ls, ch[0]->sum + ch[1]->ls);
    			rs = Max(ch[1]->rs, ch[1]->sum + ch[0]->rs);
    			val = Max(Max(ch[0]->val, ch[1]->val), Max(Max(ls, rs), ch[0]->rs + ch[1]->ls));
    		}
    	} *root;
    	void build(node *&o, int l, int r) {
    		o = new node(l, r, 0, 0, 0, 0);
    		if(l == r) {
    			o->ls = o->rs = o->sum = o->val = read();
    			return;
    		}
    		build(o->ch[0], l, o->mid());
    		build(o->ch[1], o->mid() + 1, r);
    		o->up();
    	}
    	node *query(node *o, int l, int r) {
    		if(l <= o->l && o->r <= r) return o;
    		if(r <= o->mid()) return query(o->ch[0], l, r);
    		if(l > o->mid()) return query(o->ch[1], l, r);
    		node *res = new node(l, r, 0, 0, 0, 0);
    		node *t1 = query(o->ch[0], l, r), *t2 = query(o->ch[1], l, r);
    		res->sum = t1->sum + t2->sum;
    		res->ls = Max(t1->ls, t1->sum + t2->ls);
    		res->rs = Max(t2->rs, t2->sum + t1->rs);
    		res->val = Max(Max(t1->val, t2->val), Max(Max(res->ls, res->rs), t1->rs + t2->ls));
    		return res;
    	}
    } tr;
    int main() {
    	n = read();
    	tr.build(tr.root, 1, n);
    	m = read();
    	for(int i = 1, l, r; i <= m; ++ i) {
    		l = read(); r = read();
    		printf("%d
    ", tr.query(tr.root, l, r)->val);
    	}
    	return 0;
    }
    
  • 相关阅读:
    语句
    Delphi 二维码产生和扫描
    C# 二维码扫描
    FireDac Pooling
    Delphi 7生成XML
    DataSnap Session expired处理。
    VirtualBox虚拟机中启用usb3.0却无法显示u盘的解决方法
    索引列无效情况
    Object.defineProperty() 双向数据绑定原理
    Es6常用
  • 原文地址:https://www.cnblogs.com/Paranoid-LS/p/11592810.html
Copyright © 2011-2022 走看看