線段樹維護區間前k小

2022-04-28 19:27:09 字數 1744 閱讀 6340

覺得超級鋼琴太麻煩?在這裡線段樹提供一條龍服務 。

咳咳,開始講正題!這道題我們有乙個和超級鋼琴複雜度一樣 $ o(\sum x\times logn)~ $ 的做法。因為線段數支援動態維護最小值,而取 $ max $ 操作我們可以用線段樹的 $ lazytag $ 實現(不懂可以看看**裡的標記下傳和區間修改)。所以我們主要目的就是輸出區間前 $ x $ 小,這個其實我們可以用線段樹的單點修改完成!

注意每乙個最小值我們都要花 $ log $ 的時間查詢,更改為 $ inf $ ,最後再改回來。 複雜度中有一定常數,但是演算法只用了線段樹,沒有其它資料結構魚龍混雜,跑起來效果還不錯,當然重點是碼量小一些!

#include#include#include#include#include#include#include#include#include#include#include#include#define ll long long

#define db double

#define rg register int

#define zuo k<<1,l,mid

#define you k<<1|1,mid+1,r

#define midd int mid=(l+r)>>1

#define pushd push(k,k<<1,k<<1|1)

using namespace std;

int n,m;

int x,y,v,t,sx,sv;

int as[500005];

inline int qr()

struct su

if(lz[k]>da[r]) lz[k]=0;

} inline void add1(int k,int l,int r)if(lz[k])pushd; midd;

if(x<=mid)add1(zuo);

if(y>mid) add1(you);

da[k]=min(da[k<<1],da[k<<1|1]);

} inline void add2(int k,int l,int r)

if(lz[k])pushd; midd;

if(sx<=mid) add2(zuo);

else add2(you);

da[k]=min(da[k<<1],da[k<<1|1]);

} inline su ask(int k,int l,int r);

if(lz[k])pushd; midd;

if(x<=l&&r<=y)

register su res; res.da=1e9; res.id=1001;

if(x<=mid)res=ask(zuo);

if(y>mid) res.min(ask(you));

return res;

}}tr;

int main() else //不符合題意

sx=a[j].id; sv=1e9; //讓最小值消失

tr.add2(1,1,n); //讓之前的最小值不再被選中

}if(a[t].da>=v) printf("-1");

else for(rg j=1;j<=t;++j) printf("%d ",a[j].da);

for(rg j=1;j<=t;++j)puts("");

} }return 0;

}

線段樹維護區間01

g.小 w 開關燈 problem 4467 discussion description 晚上到家小 w 通過開關燈來保持自己神經的興奮以便清醒地理筆記。n n 2 n 100,000 2 n 100,000 盞燈被連續的編號為 1 n 1 n 剛回到家的時候,所有的燈都是關閉的。小w 通過 n ...

維護序列(線段樹維護區間乘 區間加)

給定乙個長度為n的原序列和模數mod,m個操作,a,b 區間乘c,a,b 區間加c,統計 a,b 的區間和。思路 線段樹維護的還是區間和,但是這裡我們需要用到兩個懶標記,乙個記錄加法,乙個記錄乘法,乘法懶標記下傳之後要重置為1而不是0。對於乙個乘法操作,他影響的是區間和還有這個區間的加法標記 乘法標...

線段樹 離散區間,單點維護區間

這道題當時用線段樹搞不行,用主席樹搞,也不行。當場自閉。其實當時想到離散,但是沒想到用單點維護線段樹的區間。你這樣想,無非就是2e6次詢問,最多1 e9被分成最多2e6區間,我們要求的位置,一定在這2e6點的右邊第乙個。那麼把這個點,以及這個點x以及x 1的點儲存下來。維護的時候,線段樹初始化所有的...