線段樹合併+差分
對於每次修改操作(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 維護,會發現由於左兒子對右...