HDU 5306 剪枝的線段樹

2022-05-07 03:30:09 字數 1644 閱讀 1939

題意:給定\(a[1...n]\),\(m\)次操作,0表示使\([l,r]\)中的值\(a[i]=min(a[i],x)\),其餘的1是查最值2是查區間和

本題是jls的2016**題,1 2套路不說

對於操作0,維護當前最值和嚴格次大最值,更新過程分三種情況

1.當前的最大值本來就比\(x\)小或相等,直接剪枝(全域性剪枝更優,道理不必多說)

2.當前最大值大於\(x\),次大值小於等於\(x\),那麼影響到的值只有最大值,打個tag維護

3.其它情況,暴力dfs

具體地,\(max\)值的改變影響了\(sum\)值,那我們需要維護的tag需要值為\(max\)的個數,此時\(sum\)只需做差相減

**證明這種操作下依然是\(o(logn)\)的

**改得比較多,略醜

細節要注意的地方也挺多的

#include#define rep(i,j,k) for(register int i=j;i<=k;i++)

#define rrep(i,j,k) for(register int i=j;i>=k;i--)

#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])

#define print(a) printf("%lld",(ll)a)

#define println(a) printf("%lld\n",(ll)(a))

using namespace std;

const int maxn = 1e6+11;

const int nn = 1e5+11;

const int inf = 0x3f3f3f3f;

const double eps = 1e-7;

typedef long long ll;

const ll mod = 1e9+7;

ll read()

while(ch>='0'&&ch<='9')

return x*f;

}int a[maxn];

struct st

void pd(int o)

if(mx[rc]>mx[o])

lazy[o]=0;

// lazy[lc]=lazy[rc]=1;}}

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

int mid=l+r>>1;

build(lc,l,mid);

build(rc,mid+1,r);

pu(o);

}void update(int o,int l,int r,int l,int r,int v)

}pd(o);

int mid=l+r>>1;

if(l<=mid) update(lc,l,mid,l,r,v);

if(r>mid) update(rc,mid+1,r,l,r,v);

pu(o);

}ll querymax(int o,int l,int r,int l,int r)

ll querysum(int o,int l,int r,int l,int r)

}st;

int main()else if(op==1)else}}

return 0;

}

hdu 預處理 線段樹)

給n個數,m個詢問,問任意區間內與其它數互質的數有多少個 比如3個數1 2 4,詢問 1,3 那麼答案是1 千萬要記住,這樣的題目,如果你不轉變下,使勁往線段樹想 雖然轉變之後,也說要用到線段樹,但是維護的東西不同了 那麼會發現這樣的題目,區間與區間之間是無法傳遞資訊的,區間與區間是無法傳遞資訊的,...

hdu1541(線段樹的巧用)

線段樹的妙用,求乙個序列中的某個數字的前面有幾個比它小,樸素演算法是o n n 線段樹是o n logn 然後再變形下就是答案了 下面提供線段樹和樹狀陣列的解題 線段樹 include include include include include include include include i...

hdu 2795(線段樹的應用)

hdu 2795 1 思路 每個格仔的寬度都已經確定,所以一開始預設已知所有的格仔,建立線段樹,單點更新區間值 x位置的點,因為線段樹的結構類似二叉樹,所以可以將線段樹看做乙個類二叉樹,每次x先找左區間 先找下標小的區間 否則找右的區間,遞迴縮小區間,最終修改最接近x且最靠前的 點的值。2 注意 這...