SGT 線段樹維護區間最大子段和

2022-05-10 02:36:26 字數 1530 閱讀 6467

藍書p208

若將一區間分為兩部分,則必有最大子段存在於左區間 / 右區間 / 跨越中間

因此當前節點記錄該段的最大字首和,最大字尾和,段和,區間內最大子段和

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 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::pairpii;

typedef std::vector 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

tr[maxn * 4];

int arr[maxn] = ;

void push(node &now, node &ls, node &rs)

void build(int now, int l, int r)

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)

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)

int main()

return 0;

}

線段樹維護最大子段和

查詢的時候返回一整個線段樹節點,而不是乙個值,這樣才有足夠的資訊去處理問題。因為最大子段和如果跨過一些節點,那麼這個最大子段和的資訊本身不一定可以被每個節點所代表的區間的最大子段和表示,所以需要合併一些節點的資訊。include using namespace std const int maxn ...

區間最大子段和 線段樹

意思就是給你n個數,q次操作,每次改乙個值,或者詢問區間 l,r 內最大的連續子段和。線段樹維護四個東西,區間和,區間最大子段和,緊靠區間左端點的最大子段和,緊靠區間右端點的最大子段和。sum,lmax.rmax,dat,分別表示上述四種東西。sum不用說吧。對於lmax k 因為緊靠區間左端點,那...

線段樹維護區間最大子段和 列舉 HDU6638

題意 在乙個二維座標系上給你n n 2000 個點,點帶有乙個價值w 有正有負 點的座標都在 1e9,1e9 的範圍之間,可任意用乙個平行於座標軸的矩形框住一片區域,求這片區域框住的點的價值和 分析 點的座標範圍太大,離散化應能想到。離散化後可以考慮列舉左邊界,列舉左邊界後按照橫座標的依次加點 以一...