LA3938 線段樹 分治

2021-07-16 21:09:07 字數 1588 閱讀 2181

給出長度為n的整數序列,然後m次詢問,對於每次詢問,要求找到區間內的兩個下標x,y使得區間和盡量大,如果有多解,x盡量小,還有多解,那麼y也盡量小
最大連續和的分治分治演算法是解決此題的關鍵,構造一棵線段樹,並查集維護四個值:區間和sum,最大連續和max_sub、最大字首和max_pre、最大字尾和max_last。建樹與修改時注意

max_sub[o]=max(max(max_sub[o*2], max_sub[o*2+1]), max_last[o*2]+max_pre[o*2+1]),

同時應注意,查詢時傳遞的時結點型別。

//**中順便寫了修改操作

#include

#include

#include

#define maxn 100010

using namespace std;

struct tree t[3

*maxn];

int array[maxn];

void build_tree(int o, int l, int r)

int m = l + (r-l)/2;

build_tree(o*2, l, m);

build_tree(o*2+1, m+1, r);

t[o].sum = t[o*2+1].sum + t[o*2].sum;

t[o].max_pre = max(t[o*2].max_pre, t[o*2].sum+t[o*2+1].max_pre);

t[o].max_last = max(t[o*2+1].max_last, t[o*2+1].sum+t[o*2].max_last);

t[o].max_sub = max(t[o*2].max_sub, t[o*2+1].max_sub);

t[o].max_sub = max(t[o].max_sub, t[o*2].max_last+t[o*2+1].max_pre);

}tree query(int o, int l, int r, int ll, int rr)

void change(int o, int l, int r , int p, int v)

int m = l + (r-l)/2;

if(p <= m) change(o*2, l, m, p, v);

if(p > m) change(o*2+1, m+1, r, p, v);

t[o].sum = t[o*2+1].sum + t[o*2].sum;

t[o].max_pre = max(t[o*2].max_pre, t[o*2].sum+t[o*2+1].max_pre);

t[o].max_last = max(t[o*2+1].max_last, t[o*2+1].sum+t[o*2].max_last);

t[o].max_sub = max(t[o*2].max_sub, t[o*2+1].max_sub);

t[o].max_sub = max(t[o].max_sub, t[o*2].max_last+t[o*2+1].max_pre);

}int main()

線段樹分治

動態圖聯通性 可離線 loj121 給你一張無向圖,你要支援如下操作 1 刪除一條邊 2 加入一條邊 3 查詢某兩個點對間是否聯通 離線做法 線段樹分治 口胡做法 把操作的順序當做時間。每條邊維護乙個存活區間,代表這條邊在這個時間區間裡面活著。對時間軸建立一顆線段樹,從線段樹根開始dfs。進入乙個子...

線段樹分治

首先,這裡的線段樹是狹義的線段樹。而線段樹分治是一種維護時間區間的資料結構,利用線段樹的分治性使時間複雜度為log loglo g級別。維護時間區間的資料結構有cdq分治 kd tree,那麼線段樹分治和它們的區別在 呢?其實,它就是用回退操作來實現可持久化,或者說是維護了操作會影響的時間區間。我們...

線段樹分治

day2模擬被完爆了w 來學一波線段樹分治 原來一直拿它口胡其實沒寫過。然鵝這個東西和線段樹的關係 就像點分治和點分樹一樣 並不用建出來 但遍歷順序是一致的 從上到下 從左兒子到右兒子 訪問 線段樹 的所有節點 每個節點表示乙個區間 當然維護的也是區間裡的值 這就要求我們維護的東西滿足區間加法 比如...