HDU 4578 線段樹各種區間操作

2022-05-01 18:15:12 字數 1753 閱讀 7536

原題鏈結

【題意】:初始乙個長度為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,令他乘以a, 再加上b,觀察各個和的情況:

\[sum1=∑x⇒∑(a×x+b)=a*sum1+b*length

\]\[sum2=∑x^2⇒∑(a×x+b)^2=a^2 *sum2+2*a*b*sum1+b^2*ength

\]\[sum3=∑x^3⇒∑(a×x+b)^3=a^3*sum3+3*a^2*b*sum2+3*a*b^2*sum1+b^3×length

\]只執行加法時:a = 1, b = x; 只執行乘法時, a = x, b = 0; 一起執行時,\(a = t[cur].mul, b = t[cur].add\).

在置數時直接將add和mul懶標記恢復到初始值即可。

#include #define debug(x) cout << #x << " = " << x << endl; 

#define ls cur<<1

#define rs cur<<1|1

using namespace std;

typedef long long ll;

const int maxn = 2e5 + 10;

const int inf = 0x3f3f3f3f;

const int mod = 10007;

const double eps = 1e-6, pi = acos(-1.0);

struct treet[maxn<<1];

int n, m;

inline void pushup(int cur)

inline void pushdown(int cur)

if(t[cur].add != 0 || t[cur].mul != 1)

}void build(int l, int r, int cur)

void change(int l, int r, int op, int x, int cur)

else if(op == 2)

else if(op == 3)

return;

}int mid = t[cur].l + t[cur].r >> 1;

pushdown(cur);

if(l <= mid) change(l, r, op, x, ls);

if(mid < r) change(l, r, op, x, rs);

pushup(cur);

}ll query(int l, int r, int x, int cur)

int mid = t[cur].l + t[cur].r >> 1;

pushdown(cur);

ll ans = 0;

if(l <= mid) ans = (ans + query(l, r, x, ls)) % mod;

if(mid < r) ans = (ans + query(l, r, x, rs)) % mod;

return ans;

}int main()

}getchar(); getchar();

}

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 ...

HDU 4578 線段樹 三重操作

這道題自己寫了很久,還是沒寫出來,也看了很多題解,感覺多數還是看的迷迷糊糊,最後面看到一篇大佬的才感覺恍然大悟。先說下題意 就是給你n個數,每個數的初始值都是為0 然後給你m個操作 每個操作有 4 個數 op x y c 當 op 1 的時候,把 x到y 範圍內的數 都 加上 c 當 op 2 的時...

線段樹懶標記好題 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分別為一次方 二次方...