P4556 線段樹合併,差分

2021-10-04 11:32:18 字數 2450 閱讀 6070

線段樹合併+差分

對於每次修改操作(u,

v)

(u,v)

(u,v

),我們給u,v

u,vu,

v節點打上+1+1

+1的標記,給lca

(u,v

)lca(u,v)

lca(u,

v),f [l

ca(u

,v)]

f[lca(u,v)]

f[lca(

u,v)

]打上-1的標記

最後計算答案的時候,dfs

dfsdf

s一遍,將子樹內的值線段樹合併,再查詢一遍便得到該節點的答案。

#include

#define m 1000009

using

namespace std;

intread()

for(

;isdigit

(ch)

;ch=

getchar()

) re=

(re<<3)

+(re<<1)

+ch-

'0';

return re*f;

}int n,m,rt[m]

,first[m]

,nxt[m<<1]

,to[m<<1]

,cnt,num,tot,ans[m]

,rec[m]

,maxn=m-

6,dep[m]

,f[m][22

];struct treetr[m*10]

;struct data

;vectora[m]

;void

del(

int x)

intbuild()

;void

add(

int x,

int y)

void

pushup

(int k)

void

update

(int

&k,int l,

int r,

int val,

int num)

int mid=

(l+r)

>>1;

if(val<=mid)

update

(tr[k]

.l,l,mid,val,num)

;else

update

(tr[k]

.r,mid+

1,r,val,num)

;pushup

(k);

}int

merge

(int x,

int y,

int l,

int r)

;int mid=

(l+r)

>>1;

tr[x]

.l=merge

(tr[x]

.l,tr[y]

.l,l,mid)

; tr[x]

.r=merge

(tr[x]

.r,tr[y]

.r,mid+

1,r)

;del

(y),

pushup

(x);

return x;

}void

dfs1

(int u,

int fa)

}int

getlca

(int x,

int y)

for(

int i=

20;i>=

0;i--)if

(f[x]

[i]!=f[y]

[i])

x=f[x]

[i],y=f[y]

[i];

return f[x][0

];}void

dfs2

(int u,

int fa)

ans[u]

=tr[rt[u]

].maxn;

}int

main()

dfs1(1

,0);

for(

int i=

1;i<=m;i++))

; a[v]

.push_back

(data);

a[lca]

.push_back

(data);

a[f[lca][0

]].push_back

(data);

}dfs2(1

,0);

for(

int i=

1;i<=n;i++

)printf

("%d\n"

,ans[i]);

return0;

}

線段樹合併學習筆記(P4556)

直入主題 學習線段樹合併.從名字就能看出,這個東西要合併線段樹.線段樹怎麼能合併呢.暴力合就行了啊.一次從上往下的遍歷,把所有的節點資訊暴力合併,然後就沒有然後了.有兩種合併方法 一 動態開點 就是主席樹那樣的模式 可持久化了 新開乙個點記錄新的節點資訊,但是空間 巨 大 無 比 然後可能需要刪除節...

P4556 雨天的尾巴 線段樹合併

題目背景 深繪里一直很討厭雨天。灼熱的天氣穿透了前半個夏天,後來一場大雨和隨之而來的洪水,澆滅了一切。雖然深繪里家鄉的小村落對洪水有著頑固的抵抗力,但也倒了幾座老房子,幾棵老樹被連根拔起,以及田地裡的糧食被弄得一片狼藉。無奈的深繪里和村民們只好等待救濟糧來維生。不過救濟糧的發放方式很特別。題目描述 ...

P4556 雨天的尾巴 樹上差分, 樹鏈剖分

鏈結 給出一棵n n個結點的樹,有mm 次修改操作,每次操作要求將a,b a,b之間最短路徑所有點加上型別為c c的糧食11次,到最後輸出每個點所儲存的最多的糧食型別,如果有相等數量的,則輸出型別編號最小的.n,m c 1 05n,m,c 1 05整體使用 set set 維護,會發現由於左兒子對右...