傳送門biu~
考慮求lca
(x,y
) 的深度,可以把
x 到根路徑上的所有節點權值加一,再查詢
y到根路徑上的所有節點的權值和即為lc
a(x,
y)的深度。
將詢問離線,把詢問σr
i=ld
eplc
a(i,
z)拆成兩個詢問:σr
i=1d
eplc
a(i,
z)減去σl
−1i=
1dep
lca(
i,z)
。從1 到n列舉
i ,每次把
i到根路徑上的所有節點權值加一,如果在位置
i 有乙個關於
z的詢問,就查詢
z 到根路徑上的所有節點的權值和。
#include
using
namespace
std;
const
long
long mod=201314ll;
int n,q;
struct datatree[200005];
struct ques
}p[100005];int cnt;
inline
bool cmp_r(ques a,ques b)
void dfs1(int x,int father)
}void dfs2(int x,int tp)
}void buildtree(int num,int l,int r)
void pushdown(int x)
(tree[x<<1].sum+=(tree[x<<1].r-tree[x<<1].l+1)*tree[x].mark)%=mod;
(tree[x<<1|1].sum+=(tree[x<<1|1].r-tree[x<<1|1].l+1)*tree[x].mark)%=mod;
(tree[x<<1].mark+=tree[x].mark)%=mod;
(tree[x<<1|1].mark+=tree[x].mark)%=mod;
tree[x].mark=0;
}void modify(int num,int l,int r)
int mid=tree[num].l+tree[num].r>>1;
if(mid>=r) modify(num<<1,l,r);
else
if(mid1|1,l,r);
else modify(num<<1,l,mid),modify(num<<1|1,mid+1,r);
tree[num].sum=(tree[num<<1].sum+tree[num<<1|1].sum)%mod;
}inline
void modify(int x)
modify(1,pos[top[x]],pos[x]);
}long
long query(int num,int l,int r)
inline
long
long query(int x)
(re+=query(1,pos[top[x]],pos[x]))%=mod;
return re;
}int main()
dfs1(1,0);dfs2(1,1);
buildtree(1,1,n);
for(int i=1;i<=q;++i)
sort(p+1,p+cnt+1,cmp_r);
int fir=1;
while(p[fir].r==0) ++fir;
for(int i=1;i<=n;++i)
}sort(p+1,p+cnt+1,cmp_id);
for(int i=1;i<=cnt;i+=2) printf("%lld\n",(p[i].sum-p[i+1].sum+mod)%mod);
return
0;}
LCA 樹鏈剖分
剛打完lca板子,寫個東西記下 dfs第一遍求出 結點i的深度,以i為根的子樹大小,結點i的父親,並求出重鏈 dfs第二遍求出 結點i所在重鏈的鏈頂 如果在重鏈上 開始lca,兩個點往上找,深度大的點就往上跳,這個點如果在重鏈上,就跳到所在重鏈的鏈頂的父親處,在輕鏈上,就直接跳到自己父親上 洛谷lc...
樹鏈剖分求LCA
這裡先推薦兩道練習的裸題 首先是求點 codevs4605 lca 就是求兩個點的公共祖先,每次詢問xor上上乙個詢問的答案。先是兩遍dfs dfs1 把dep siz son求出來 dfs2 求出top和w siz v 表示以v為根的子樹的節點數 dep v 表示v的深度 根深度為1 top v ...
樹鏈剖分求lca
題目描述 給一棵有根樹,以及一些詢問,每次詢問樹上的2 個節點a b,求它們的最近公共祖先.輸入第一行乙個整數n.接下來n 個數,第i 個數fi 表示i 的父親是fi.若fi 0,則i 為樹根.接下來乙個整數m.接下來m 行,每行2 個整數a b,詢問節點 a xor lastans bxor la...