HDU 4578 線段樹 三重操作

2022-05-28 13:57:12 字數 2552 閱讀 4348

這道題自己寫了很久,還是沒寫出來,也看了很多題解,感覺多數還是看的迷迷糊糊,最後面看到一篇大佬的才感覺恍然大悟。

先說下題意:

就是給你n個數,每個數的初始值都是為0

然後給你m個操作

每個操作有 4 個數  op x y c

當 op==1 的時候,把 x到y 範圍內的數 都  加上 c

當 op==2 的時候,把 x到y 範圍內的數 都  乘以 c

當 op==3 的時候,把 x到y 範圍內的數 都  等於  c

當 op==4 的時候,把 x到y 範圍內的 每乙個數 的 c 次方的和 輸出(注意,當op等於4的時候,c的範圍為1~3)

下面說說思路:

關鍵就是在於這個 懶惰值的傳遞,和區間的每乙個值是否都相等的問題

一.先說說樹的資料

這個大家參考下就可以,實現的方法有很多,不一定需要這麼寫,把這個先放上來是便於理解。(我這麼寫是因為我太菜了)

struct

data tree[m << 2];

二.再說這個區間值都相等

我們可以知道,如果區間內的每乙個值都相等,那麼我們只要 求 其中乙個的值的c次方,然後把該數乘以(右邊界  減去 左邊界  再加 1 ),便是該區間值的次方總和了

如果該區間的每乙個值不相等,那麼我們必須接著向下探索,直到 找到 乙個  區間內的每乙個值都相等  的區間,最壞的情況也就是找到葉節點。

三.懶惰值的傳遞

如果這個區間的每乙個值都相等,那麼它的左右子區間肯定也都是相等的。

如果這個區間不是全等區間,那麼我們就沒必要傳遞懶惰值,因為你這個區間每乙個值不一定相等 ;  但是如果是全等區間,就要傳遞懶惰值。

如果我們在更新資料的過程中,需要用到傳遞懶惰值,那麼肯定是要修改這個區間的某乙個子區間,所以傳遞後,這個區間肯定不會再是全等區間

四.資料的更新

我們在更新完值後,肯定也需要更新區間是否相等的資訊

有三種情況:

1.如果該區間的左右子區間 都不是 全等區間的話,那這個區間肯定也 不是 全等區間

2.如果該區間的左右子區間 都是 全等區間, 但是它們的 葉節點的值都 不相等,那麼這個區間肯定 也不是 全等區間

3.如果該區間的左右區間 都是 全等區間,並且 它們的 葉節點的值都 全等,那麼這個區間 肯定是 全等區間

下面上**:

#include #include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define m 100005

#define mod 10007

#define inf 0x3f3f3f3f

#define left k<<1

#define right k<<1|1

#define ms(a,b) memset(a,b,sizeof(a))typedef

long

long

ll;using

namespace

std;

struct

data tree[m << 2

];ll ans, temp;

ll op, c, p;

intx, y, n, m;

void built(int l, int r, int

k) void down(int

k) void updata(int

k)

else

if (op == 2)

else

return

; }

if (tree[k].dif)down(k);//

如果該區間是全等區間,那麼就要傳遞懶惰值,並且傳遞後該區間肯定是 不全等區間

int mid = (tree[k].l + tree[k].r) >> 1

;

if (x <=mid)updata(left);

if (y >mid)updata(right);

//傳遞後三種情況分析更新

if (!tree[left].dif || !tree[right].dif)tree[k].dif = false

;

else

}}void query(int

k)

if (tree[k].dif)down(k);//

如果該區間是全等區間,那麼就要傳遞懶惰值,並且傳遞後該區間肯定是 」全等區間「

int mid = (tree[k].l + tree[k].r) >> 1

;

if (x <=mid)query(left);

if (y >mid)query(right);

}int

main()

else}}

return0;

}

HDU 4578 線段樹各種區間操作

原題鏈結 題意 初始乙個長度為n的陣列全為0,有m個操作,輸入op,l,r,x。op 1時,把 l,r 中的所有數加上x op 2時,把 l,r 中的所有樹乘上x op 3時,把 l,r 中的所有數全置為x op 4時,輸出 l,r 中所有數的 x 方的和 思路 令 x a x b 即對乙個x,令他...

hdu4578 (多標記線段樹)

對於乙個區間有4個操作 1.將a b都加上c 2.將a b都乘上c 3.將a b都變成c 4.查詢a b的每個數的p次方的和。p 1,2,3 平方和這樣來推 a c 2 a 2 2ac c 2 即 sum2 rt sum2 rt 2 sum1 rt c r l 1 c c 立方和這樣推 a c 3 ...

線段樹懶標記好題 HDU4578

1 1 x y c 代表 把區間 x,y 上的值全部加c 2 2 x y c 代表 把區間 x,y 上的值全部乘以c 3 3 x y c 代表 把區間 x,y 上的值全部賦值為c 4 4 x y p 代表 求區間 x,y 上值的p次方和1 p 3 維護sum1,sum2,sum3分別為一次方 二次方...