LNOI2014 LCA 差分 樹剖

2021-09-28 12:07:36 字數 1591 閱讀 2117

葉子最可愛啦qwq!

每次詢問乙個區間和乙個點,求這個區間所有點和給定點的lca的深度和。

深度和是吧。

lca的深度和有乙個很優良的性質。你把乙個點到根的權值都+1,查另乙個點到根的權值就是這個深度。

那問題轉化成了鏈加鏈求和。

不過有q個詢問哦。怎麼辦呢?

很明顯這個詢問應該被去掉。

我們不乙個詢問乙個詢問查詢。

我們直接從1號點開始加入貢獻。對於乙個詢問,加到l-1時統計一下,加到r時統計一下,然後兩者減減就行。

利用了差分的思想。

當然是樹剖+線段樹。

warning:不要像我一樣,跳top時交換了top沒交換自己。

#includeusing namespace std;

#define in read()

int in

while(isdigit(ch))return cnt*f;

}const int mod=201314;

struct nodet[200003];

int n,m;

int first[100003],nxt[200003],to[200003],tot;

void add(int a,int b)

int id[100003],top[100003],son[100003],size[100003],dep[100003],fa[100003];

void pushup(int u)

void pushdown(int u)

}int queryseg(int u,int ql,int qr)

void segmo(int u,int ql,int qr,int key)

struct bilique[100003];int cnt;

int ans1[100003],ans2[100003];

void dfs1(int u,int faa)

}void dfs2(int u,int tp)

}void build(int u,int l,int r)int mid=(l+r)>>1;

build(u*2,l,mid);build(u*2+1,mid+1,r);

}bool cm(bili a,bili b)

int main()

build(1,1,n);dfs1(1,0);dfs2(1,1);

//for(int i=1;i<=n;i++)cout

for(int i=1;i<=m;i++)

sort(que+1,que+cnt+1,cm);

for(int i=1,pos=0;i<=cnt;i++)

que[i].ans=query(1,que[i].z);

if(que[i].flag)(ans[que[i].belong]+=que[i].ans)%=mod;

else ((ans[que[i].belong]-=que[i].ans)+=mod)%=mod;

} for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);

return 0;

}

離線操作 樹鏈剖分 LNOI2014 LCA

題目描述 給出乙個n個節點的有根樹 編號為0到n 1,根節點為0 乙個點的深度定義為這個節點到根的距離 1。設dep i 表示點i的深度,lca i,j 表示i與j的最近公共祖先。有q次詢問,每次詢問給出l r z,求 l i r dep lca i,z sum dep lca i,z l i r ...

LNOI2014 LCA 解題報告

對於一棵 n 個節點的樹,給出 m 次詢問,每次給出 l,r,x 求 sum limits r depth lca i,x n,m le 5 times 10 4 1 le l le r le n x le n 一道不錯的題目。說明有時候用一些其他的做法求乙個簡單的東西也可以幫助思考。對於我,求lc...

LCA 樹鏈剖分

剛打完lca板子,寫個東西記下 dfs第一遍求出 結點i的深度,以i為根的子樹大小,結點i的父親,並求出重鏈 dfs第二遍求出 結點i所在重鏈的鏈頂 如果在重鏈上 開始lca,兩個點往上找,深度大的點就往上跳,這個點如果在重鏈上,就跳到所在重鏈的鏈頂的父親處,在輕鏈上,就直接跳到自己父親上 洛谷lc...