P3038 [USACO11DEC]Grass Planting G(樹鏈剖分邊權轉點權)
https://www.luogu.com.cn/problem/P3038
給出一棵n個節點的樹,有m個操作,操作為將一條路徑上的邊權加一或詢問某條邊的權值
思路:邊權轉點權
過程:參考羅老師
如果把邊權轉為點權,就能按前面給出的“樹鏈剖分 + 線段樹”來解決。
例如下圖(1),若把邊權轉為點權,顯然只能把每條邊上的邊權賦給這條邊下層的結點,得到圖(2)。程式設計操作是:比較邊(u, v)的兩點的deep[u]、deep[v],把邊權賦給更深的那個結點。
圖4 圖(1)邊權樹 (2)轉化為點權樹
轉換為點權後,樹剖的操作基本上一樣。但是,區間求和和區間更新操作都有一點問題。
(1)區間求和。例如圖(1)求從d到e的路徑,d-b-e的長度是7 + 3 = 10;但是圖(2)變成了7 + 2 + 3 = 12,多算了b點的權值。
(2)區間修改。例如圖(1)中把從d到e的路徑上的邊d-b、b-e都減1,此時邊b-a並沒有被影響到;但是在圖(2)中,把d、b、e三個結點的值都減了1,而b點的值是不該被減的。
觀察到b = LCA(d, e),所以解決方法是不要處理LCA:
(1)區間[L, R]求和時,不計算LCA(L, R)的值;
(2)區間[L, R]更新時,不更新LCA(L, R)的值。
https://blog.csdn.net/weixin_43914593/article/details/109709506
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+1000;
typedef long long LL;
typedef pair<LL,LL>P;
struct Tree{
LL l,r,sum,tag;
}tree[maxn*4];
LL new_w[maxn];
///線段樹部分
void push_up(LL p){
tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;
}
void addtag(LL p,LL d){
tree[p].tag+=d;
tree[p].sum+=d*(tree[p].r-tree[p].l+1);
}
void push_down(LL p){
if(tree[p].tag!=0){
addtag(p*2,tree[p].tag);
addtag(p*2+1,tree[p].tag);
tree[p].tag=0;
}
}
void build(LL p,LL l,LL r){
tree[p].l=l;tree[p].r=r;tree[p].tag=0;tree[p].sum=0;
if(l==r){tree[p].sum=new_w[l];return;}
LL mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
push_up(p);
}
void modify(LL p,LL l,LL r,LL d){
if(l<=tree[p].l&&r>=tree[p].r){
addtag(p,d);
return;
}
push_down(p);
LL mid=(tree[p].l+tree[p].r)>>1;
if(l<=mid) modify(p*2,l,r,d);
if(r>mid) modify(p*2+1,l,r,d);
push_up(p);
}
LL query(LL p,LL l,LL r){
if(l<=tree[p].l&&r>=tree[p].r){
return tree[p].sum;
}
push_down(p);
LL mid=(tree[p].l+tree[p].r)>>1;
LL ans=0;
if(l<=mid) ans+=query(p*2,l,r);
if(r>mid) ans+=query(p*2+1,l,r);
return ans;
}
///樹鏈剖分部分
LL siz[maxn],son[maxn],dep[maxn],fa[maxn];
LL top[maxn];
LL id[maxn],tot=0,a[maxn];
vector<P>g[maxn];///first存要到的節點,second存邊權
void predfs(LL u,LL father){
siz[u]=1;dep[u]=dep[father]+1;
fa[u]=father;
for(LL i=0;i<g[u].size();i++){
LL v=g[u][i].first;
if(v==father) continue;
a[v]=g[u][i].second;///點權轉邊權
predfs(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]){
son[u]=v;
}
}
}
void dfs(LL u,LL topx){
top[u]=topx;
id[u]=++tot;
new_w[tot]=a[u];
if(!son[u]) return;///邊界葉子節點
dfs(son[u],topx);
for(LL i=0;i<g[u].size();i++){
LL v=g[u][i].first;
if(v==fa[u]||v==son[u]) continue;
dfs(v,v);
}
}
void modify_path(LL u,LL v,LL d){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]){
swap(u,v);
}
modify(1,id[top[u]],id[u],1);
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
modify(1,id[u],id[v],1);
LL LCA=dep[u]<dep[v]?u:v;
modify(1,id[LCA],id[LCA],-1);
}
LL query_path(LL u,LL v){
LL ans=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]){
swap(u,v);
}
ans+=query(1,id[top[u]],id[u]);
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
ans+=query(1,id[u],id[v]);
LL LCA=dep[u]<dep[v]?u:v;
ans-=query(1,id[LCA],id[LCA]);
return ans;
}
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL n,m;cin>>n>>m;
for(LL i=1;i<n;i++){
LL u,v;cin>>u>>v;
g[u].push_back({v,0});
g[v].push_back({u,0});
}
predfs(1,0);
dfs(1,1);
build(1,1,n);
while(m--){
char op;LL l,r;
cin>>op>>l>>r;
if(op=='P'){
modify_path(l,r,1);
}
if(op=='Q'){
cout<<query_path(l,r)<<endl;
}
}
return 0;
}
相關文章
- 樹鏈剖分
- [OI] 樹鏈剖分
- 2024.3.14 樹鏈剖分
- 淺談樹鏈剖分
- 樹鏈剖分總結
- Something about 樹鏈剖分
- 【筆記/模板】樹鏈剖分筆記
- #8. 「模板」樹鏈剖分
- [LOJ139]-樹鏈剖分
- 「學習筆記」樹鏈剖分筆記
- 樹鏈剖分學習筆記筆記
- 對樹鏈剖分的愛 題解
- P8025 【樹鏈剖分求祖先】
- 樹鏈剖分模板+入門題 SPOJ - QTREEQT
- 樹鏈剖分解析
- bzoj4551: [Tjoi2016&Heoi2016]樹(樹鏈剖分)
- 一起來學習樹鏈剖分吧!
- bzoj3531: [Sdoi2014]旅行(樹鏈剖分+線段樹)
- 樹剖 dsu on tree 長鏈
- TZOJ 8472 : Tree (重鏈剖分+線段樹) POJ 3237
- 長鏈剖分模板
- 長鏈剖分筆記筆記
- 迴文樹線上剖分???
- BF的資料結構題單-提高組——樹鏈剖分資料結構
- P1505 [國家集訓隊]旅遊 (樹鏈剖分)
- 熟練剖分(tree) 樹形DP
- bzoj3626: [LNOI2014]LCA(離線處理+樹鏈剖分)
- 重鏈剖分題目選講
- 【2024-ZR-C Day 6】資料結構(4):樹(重、長)鏈剖分、虛樹、dsu on tree資料結構
- 複雜多邊形的三角剖分
- 權值線段樹
- 樹剖(不太會)
- POJ 1182 食物鏈【擴充套件域 | 邊帶權並查集】套件並查集
- networkx基礎用法:新增節點、新增邊、刪除節點、刪除邊、計算度、賦權重
- openGauss-控制權和訪問權分離
- 點分樹
- Note - 樹分治(點分治、點分樹)
- 5G/NR 上行免授權