覺得超級鋼琴太麻煩?在這裡線段樹提供一條龍服務 。
咳咳,開始講正題!這道題我們有乙個和超級鋼琴複雜度一樣 $ 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的點儲存下來。維護的時候,線段樹初始化所有的...