線段樹 CDQ分治 迴轉壽司

2021-08-09 17:20:41 字數 1859 閱讀 5002

給你乙個序列,求連續子串行和在【l,r】之間的方案數

n≤100000,|ai|≤100000,0≤l, r≤109.

這是我打的第一題cdq(太菜了)

我對這題印象很深刻

當時大家有各種做法

好像都是線段樹?

然後這時出現了一股清流

dhr的cdq分治(orz dhr 好短啊)

然後愉悅的改完後就沒管了

很久以後yzx講cdq分治時想到我曾經打過一道

先遞迴

再更新答案

然後sort

回溯

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

int n,l,r,a[100050];

ll s[100050],ans;

void solve(int p,int q)

sort(s+p,s+q+1);

}int main()

solve(0,n);

printf("%lld",ans);

}

現在再補上一種值域線段樹的做法

對於字首和s【i】(i表示以i為末尾) 滿足l

<=s【

j】−s

【i】<=r(

i得 s【

j】−r

<=s【

i】<=s【

j】−l

將s【i】插入一顆值域線段樹(初始化時插入0)

對於每個s【j】查詢值域在[s【j】-l,s【j】-r]之間的s【i】個數

#include

#define inf 10000000000

#define n 100010

#define mid ((l+r)>>1)

using namespace std;

typedef long long ll;

ll ans,sum,l,r;

int n,u,v,top,p,t[n*40],lc[n*40],rc[n*40],rt;

void ins(int &x,ll l,ll r)

int que(int

x,ll l,ll r)

int main()

printf("%lld\n",ans);

}

還有一種以i為首的樹狀陣列

鏈結感覺二分可以換成two pointer

或者可以看orz 曾老師的**

#include

#include

#define ll long long

using

namespace

std;

inline ll rd()

#define mxn 100233

ll n, l, r, i, j;

paira[mxn];

#define fir(i) a[i].first

#define sec(i) a[i].second

//第i小的字首的值與序號

ll b[mxn];

inline

void add(ll i, ll x)

inline ll sum(ll i)

ll ans;

inline ll solve(ll m)

return ans;

}inline

void debug()

int main()

線段樹分治

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

線段樹分治

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

線段樹分治

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