題目大意:n個點,m條邊,然後q次詢問,因為在樹上,兩個點能確定一條直線,我們可以對這條直線上的所有值進行加減操作,也可以單點詢問。
各個陣列的作用:sto是剛開始的輸入資料,head是前向星,dfsnum指的是dfs序,depth指的是每個點的深度son指的是每個節點的重兒子,father指的是每個點的父節點,size指的是以當前點為根節點的樹,ord指的是遍歷順序,cost指的是編號之後的每個點,top指的是當前的這條重鏈的最頂端的那個點,剩下的就是線段樹的陣列了。
注意點:我們通過兩個dfs來給這些陣列賦值,通過第乙個dfs,我們可以把depth和father,size,son求出來,剩下的ord和top通過第二個dfs求出來,為什麼使用兩個dfs?我的理解就是,第乙個dfs和第二個dfs的遍歷條件並不相同,第乙個dfs就是能走就走,第二個dfs是在按照已經分好鏈的前提下進行走的,也就是說這裡的ord陣列並不能在第乙個dfs中實現,只能在第二個陣列中實現。(後續有新的理解會繼續補充)。
ac**:
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9
using
namespace
std;
10 # define inf 0x3f3f3f3f
11 # define ll long
long
12 # define lson l,m,rt<<1
13 # define rson m+1,r,rt<<1|1
14const
int maxn = 5e4+100;15
intsto[maxn],head[maxn],edgnum,dfsnum,depth[maxn];
16int
son[maxn],father[maxn],size[maxn],ord[maxn],cost[maxn],top[maxn];
17int tree[maxn<<2],lazy[maxn<<2
];18
struct
node
19 edge[maxn<<2
];23
void addedge(int fr,int
to)24
29void dfs1(int fr,int rt,int
dep)
3046}47
}48void dfs2(int fr,int
rt)4962}
63}64void
init()
6570
void up(int
rt)71
74void down(int len,int
rt)7584}
85void buildtree(int l,int r,int
rt)86
94int m=(l+r)>>1;95
buildtree(lson);
96buildtree(rson);
97up(rt);98}
99void update(int l,int r,int rt,int l,int r,int
p)100
107 down(r-l+1
,rt);
108int m=(l+r)>>1
;109
if(l<=m)
110update(lson,l,r,p);
111if(r>m)
112update(rson,l,r,p);
113up(rt);
114}
115void update(int n,int x,int y,int
p)116
125 update(1,n,1
,ord[tx],ord[x],p);
126 x=father[tx],tx=top[x];
127}
128if(depth[x]129132 update(1,n,1
,ord[y],ord[x],p);
133}
134int query(int l,int r,int rt,int
pos)
135140 down(r-l+1
,rt);
141int ans=0
;142
int m=(l+r)>>1
;143
if(pos<=m)
144 ans+=query(lson,pos);
145if(pos>m)
146 ans+=query(rson,pos);
147return
ans;
148up(rt);
149}
150int
main()
151161
intt1,t2;
162for(int i=1; i<=m; i++)
163168
init();
169char str[10
];170 buildtree(1,n,1
);171
intt3;
172while(q--)
173180
else
if(str[0]=='q'
)181
186else
if(str[0]=='d'
)187
191}
192}
193return0;
194 }
數鏈剖分(Housewife Wind )
題目大意 給你n,q,s。n指的是有n個點,q代表有q次詢問,s代表的是起點。然後接下來會有n 1條邊,雙向邊,帶有權值,對於q次詢問,如果輸入的第乙個數是1,然後接下來會輸入兩個數,t1,t2。t帶邊將第t1條邊的權值改成t2.如果第乙個數是0,接下來會輸入乙個t,詢問從s到t的花費。具體思路 對...
數鏈剖分基礎講解
在一棵樹上進行路徑的修改 求極值 求和 乍一看只要線段樹就能輕鬆解決,實際上,僅憑線段樹是不能搞定它的。我們需要用到一種貌似高階的複雜演算法 樹鏈剖分。樹鏈,就是樹上的路徑。剖分,就是把路徑分類為重鏈和輕鏈。重兒子 siz u 為v的子節點中siz值最大的,那麼u就是v的重兒子。輕兒子 v的其它子節...
樹鏈剖分 樹鏈剖分講解
好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...