BZOJ 1798 維護序列

2021-07-10 13:48:25 字數 1969 閱讀 8128

線段樹~

這(d)道(q)題(s)告訴我說:「你沒學過線段樹」

嗯……

這題要好好想想……qaq

來吧首先要明確的事情是

delta[now]記錄的是已經對當前點做過的,但是還沒有對當前點的兒子做過的操作

嗯……

我們就這樣

慢慢的退一下

嗯 標記是給兒子用的

嗯 是給兒子用的

奉獻精神

然後,對於這個題,我們可以把所有操作統一為對該節點*x+y的形式

void change(int l,int r,ll add,ll mult,int p)

那麼區間乘就成了change(l,r,0,v,1);

那麼區間加就成了change(l,r,v,1,1);

標記是什麼?

對目前的答案進行標記該有的操作之後會得到真實的答案

真理往往隱蔽在眾多表象的茫茫迷霧之中,而標記就像穿透這迷霧的明燈,引導著探索者到達真理的彼岸

(old_ans * mult) + add = new_old

標記的作用是引導兒子走上正軌

所以說下放標記的時候要將兒子的ans計算出來

嗯然後怎麼更新標記

這成了大問題 設

為了使得

(sum * a + b) * c + d == sum * x + y

sum * a * c + b * c + d == sum * x + y

x = a * c

y = b * c + d

然後就可以更新了~

嗯 kill

#include 

#include

#include

#include

#define l(x) (x << 1)

#define r(x) (x << 1 | 1)

#define sz(x) (tree[x].r - tree[x].l + 1)

using

namespace

std;

const

int maxn = 100000 + 5;

typedef

long

long ll;

int p;

struct dot

tree[maxn << 2];

int num[maxn];

void update(int p)

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

int mid = (l + r) >> 1;

build(l,mid,l(p));

build(mid + 1,r,r(p));

update(p);

return;

}void spread(int p)

void change(int l,int r,ll add,ll mult,int p)

spread(p);

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

if(l <= mid)change(l,r,add,mult,l(p));

if(mid < r)change(l,r,add,mult,r(p));

update(p);

return;

}ll ask(int l,int r,int p)

int n,m;

int q,a,b;

ll v;

int main()

}return

0;}

BZOJ 1798, 維護序列

傳送門 維護乙個數列,要求支援區間加 區間乘以及查詢操作。很裸的線段樹,難點在於加法和乘法的操作順序。標記下傳時應先打乘法標記,再打加法標記,同時更新時還要用乘法標記維護加法標記。include typedef long long ll const int n 100005 int n,p,m,x,...

bzoj1798 ahoi2009 維護序列

time limit 30 sec memory limit 64 mb submit 3714 solved 1364 submit status discuss 老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。有長為n的數列,不妨設為a1,a2,an 有如下三種操作形式 1 把數列...

BZOJ 1500 維護序列

bzoj 1500 傳送門 可能平衡樹維護序列的所有操作都在這了吧 對序列的維護 fhq treap 和 splay 都能做 有幾個注意點 1 維護序列時始終記得第 k 大指的是序號,與權值無關 2 注意對0的初始化,畢竟如果無葉子結點時會用到 3 如果資料總量過大要資料 用佇列記錄被刪除的節點,同...