zoukankan      html  css  js  c++  java
  • [SGT] 线段树维护区间最大子段和

    蓝书P208

    https://vjudge.net/problem/SPOJ-GSS1


    若将一区间分为两部分,则必有最大子段存在于左区间 / 右区间 / 跨越中间

    因此当前节点记录该段的最大前缀和,最大后缀和,段和,区间内最大子段和

    	now.sum = ls.sum + rs.sum;
    	now.lmax = max(ls.lmax, ls.sum + rs.lmax);
    	now.rmax = max(rs.rmax, rs.sum + ls.rmax);
    	now.val = max(ls.val, max( rs.val, ls.rmax + rs.lmax) );

    修改,建树时直接按定义push

    查询相当于建颗查询区间内的子树再暴力合并至根节点返回

    代码

    /*
        Zeolim - An AC a day keeps the bug away
    */
     
    //pragma GCC optimize(2)
    #include <bits/stdc++.h>
    using namespace std;
    
    #define mp(x, y) make_pair(x, y)
    #define fr(x, z, y) for(int x = z; x < y; ++x)
    
    typedef long long ll;
    typedef double ld;
    typedef std::pair<int, int> pii;
    typedef std::vector <short> vi;
    //typedef __int128 ill;
    
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 1e18;
    const ll MOD = 1e9 + 7;
    const int MAXN = 1e6 + 100;
    
    int n, m;
    
    struct node
    {
    	int l, r;
    	int val;
    	int sum, lmax, rmax;
    }tr[MAXN * 4];
    
    int arr[MAXN] = {0};
    
    void push(node &now, node &ls, node &rs)
    {
    	now.sum = ls.sum + rs.sum;
    	now.lmax = max(ls.lmax, ls.sum + rs.lmax);
    	now.rmax = max(rs.rmax, rs.sum + ls.rmax);
    	now.val = max(ls.val, max( rs.val, ls.rmax + rs.lmax) );
    }
    
    void build(int now, int l, int r)
    {
    	tr[now].l = l, tr[now].r = r;
    	int mid = (l + r) / 2;
    	if(l == r) {tr[now].val = tr[now].sum = tr[now].lmax = tr[now].rmax = arr[l]; return;}
    	build(now * 2, l, mid);
    	build(now * 2 + 1, mid + 1, r);
    	push(tr[now], tr[now * 2], tr[now * 2 + 1]);
    }
    
    void change(int now, int p, int v)
    {
    	if(tr[now].l == tr[now].r) { tr[now].val = tr[now].sum = tr[now].lmax = tr[now].rmax = v; return;}
    	int mid = (tr[now].l + tr[now].r) / 2;
    	if(p <= mid) change(now * 2, p, v);
    	if(p > mid) change(now * 2 + 1, p, v);
    	push(tr[now], tr[now * 2], tr[now * 2 + 1]);
    }
    
    node ask(int now, int l, int r)
    {
    	if(l <= tr[now].l && r >= tr[now].r) return tr[now];
    	int mid = (tr[now].l + tr[now].r) / 2;
    	if(r <= mid) return ask(now * 2, l, r);
    	if(l > mid) return ask(now * 2 + 1, l, r);
    	node ls = ask(now * 2, l, r), rs = ask(now * 2 + 1, l, r), ans;
    	push(ans, ls, rs);
    	return ans;
    }
    
    
    int main()
    {  
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        //freopen("d:out.txt","w",stdout);
      	//freopen("d:in.txt","r",stdin);
      	cin >> n;
      	fr(i, 1, n + 1)
      		cin >> arr[i];
      	build(1, 1, n);
      	cin >> m;
      	int op, x, y;
      	fr(i, 0, m)
      	{
      		cin  >> x >> y;
      		cout << ask(1, x, y).val << '
    ';
      	}
        return 0;
    }
  • 相关阅读:
    人物装备的选取
    状压 + 背包
    村庄之间建立邮局
    woj
    括号匹配算面积(模拟)
    流程控制之if
    周末练习题(第一周)
    day04作业
    流程控制之for
    Python流程控制之while
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270352.html
Copyright © 2011-2022 走看看