復健3 線段樹

2022-07-11 23:51:13 字數 1334 閱讀 9017

哦上帝啊,如果我有罪,請叫法律來制裁我,而不是寫了個線段樹調好幾天,這篇復健鴿了兩三天了(謝罪)因為最近在和學長聊天orz(我是什麼臭魚爛蝦我這就爬)

個人覺得線段樹的思想比樹狀陣列要簡單些,但是**量確實是樹狀陣列更優美orz

樹狀陣列是從最基礎元素開始標為1,用二進位制整數下標存字首和,但是線段樹的話是從頂部節點開始標為1,每次用父節點2代表左子節點,父節點2+1代表右子節點,是乙個完整形狀的二叉樹,別的應該都很好理解,主要是懶標記的處理,這就好比把操作單獨存乙個陣列裡,不每次都追溯到這個點本身,而是將對於該點的所有操作完成後對,當需要取出這個點的值的時候對這個點操作一次即可,這也正是線段樹的優越之處

線段樹大概是好在可以很方便的同時維護很多東西,**的話這裡就不放最基礎版本的洛谷p3372線段樹1了,直接放洛谷3373線段樹2了

#includeusing namespace std;

typedef long long ll;

#define l(x) t[x].l

#define r(x) t[x].r

#define sum(x) t[x].sum

#define add(x) t[x].add

#define mul(x) t[x].mul

const int maxn=100005;

struct tree t[maxn*4];

ll p,n,m;

int a[maxn];

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

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

build(2*x,l,mid);

build(2*x+1,mid+1,r);

sum(x)=(sum(2*x)+sum(2*x+1))%p;

}void update(int x)

void change(int x,int l,int r,int z,int o)

if(add(x)||mul(x)!=1) update(x);

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

if(l>mid) change(2*x+1,l,r,z,o);

else if(r<=mid) change(2*x,l,r,z,o);

else

sum(x)=(sum(2*x)+sum(2*x+1))%p;

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

int main()

build(1,1,n);

for(int i=1;i<=m;i++)

else printf("%lld\n",query(1,x,y));

}}```

線段樹練習3

給定一條長度為m的線段,有n個操作,每個操作有3個數字x,y,z表示把區間 x,y 染成顏色z。規定 線段的顏色可以相同。連續的相同顏色被視作一段。詢問染色後的線段被分為多少段。線段樹 cover 1表示該區間由多種顏色組成。cover 0表示該區間只有一種單一的顏色cover。和線段樹練習2差不多...

Codevs P1082 線段樹練習3 線段樹

題目描述 description 給你n個數,有兩種操作 1 給區間 a,b 的所有數增加x 2 詢問區間 a,b 的數的和。輸入描述 input description 第一行乙個正整數n,接下來n行n個整數,再接下來乙個正整數q,每行表示操作的個數,如果第乙個數是1,後接3個正整數,表示在區間 ...

線段樹 02 構建線段樹

public inte ce merger 不能再縮小的基本問題是 對treeindex指向的節點的情況進行討論 public class segmenttree 在treeindex的位置建立表示區間 l.r 的線段樹 private void buildsegmenttree int treei...