日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

bzoj3626:[LNOI2014]LCA

發布時間:2023/12/18 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bzoj3626:[LNOI2014]LCA 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:http://www.lydsy.com/JudgeOnline/problem.php?id=3626

Description

給出一個n個節點的有根樹(編號為0到n-1,根節點為0)。一個點的深度定義為這個節點到根的距離+1。
設dep[i]表示點i的深度,LCA(i,j)表示i與j的最近公共祖先。
有q次詢問,每次詢問給出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
(即,求在[l,r]區間內的每個節點i與z的最近公共祖先的深度之和)

Input

第一行2個整數n q。
接下來n-1行,分別表示點1到點n-1的父節點編號。
接下來q行,每行3個整數l r z。

Output

輸出q行,每行表示一個詢問的答案。每個答案對201314取模輸出

Sample Input

5 2
0
0
1
1
1 4 3
1 4 2

Sample Output

8
5

HINT

共5組數據,n與q的規模分別為10000,20000,30000,40000,50000。

題解

樹鏈剖分,雖然題目是lca,然而好像并沒有什么關系。題目查詢的是在l到r區間中,與z的最近公共祖先的深度之和。然后很明顯可以知道兩點到根節點經過的共同節點個數為其公共祖先的深度,比如樣例中4和5共同經過1和2,而他們的最近公共祖先為2,其深度為2。然后求l到r之間的,可以轉換為[1,l]-[1,r-1]的差。那么就可以對于查詢離線,把詢問分成兩部分,按值來排序,比如[1,4,3],就分成[0,3]和[4,3]。查詢時把需要加的點一個個加進去,當到達一個點恰好為某個詢問的值,那么就可以把這個詢問的答案來更新一下了。值的定義為分成兩部分后區間的右端點,左端點恒為1。

代碼

#include<iostream> #include<cmath> #include<cstring> #include<cstdlib> #include<cstdio> #include<ctime> #include<queue> #include<vector> #include<algorithm> #define mo 201314 #define N 300010 using namespace std; long long sum,ans[N]; int tot,p,q,n,u,v; long long lazy[N],b[N]; int siz[N],fa[N],son[N],dep[N],head[N],top[N],w[N]; struct h1{int next,to;}tu[N]; struct data{int l,f,w,wei;}a[2*N]; int getint() {int res=0,w=1;char ch=getchar();while ((ch>'9' || ch<'0')&&ch!='-') ch=getchar();if (ch=='-') w=-1,ch=getchar();while (ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar();return res*w; } void link(int x,int y) {tu[++sum].next=head[x]; head[x]=sum; tu[sum].to=y; } void dfs1(int p) {siz[p]=1;for (int i=head[p];i;i=tu[i].next){int v=tu[i].to;if (v==fa[p]) continue;dep[v]=dep[p]+1;dfs1(v); siz[p]+=siz[v]; if (siz[v]>siz[son[p]]) son[p]=v;} } void dfs2(int p,int t) {top[p]=t; w[p]=++tot;if (son[p]) dfs2(son[p],t);for (int i=head[p];i;i=tu[i].next)if (tu[i].to!=son[p]&&tu[i].to!=fa[p]) dfs2(tu[i].to,tu[i].to); } bool cmp(data a,data b) {return a.l<b.l;} void tree_add(int x,int l,int r,int L,int R) {if (l==L&&r==R) lazy[x]=(lazy[x]+1)%mo;else{b[x]=(b[x]+R-L+1)%mo;int mid=(l+r)>>1;if (L>mid) tree_add((x<<1)+1,mid+1,r,L,R);else if (R<=mid) tree_add(x<<1,l,mid,L,R);else tree_add(x<<1,l,mid,L,mid),tree_add((x<<1)+1,mid+1,r,mid+1,R);} } void tree_find(int x,int l,int r,int L,int R) {if (l==L&&r==R) sum=(sum+b[x]+1LL*lazy[x]*(r-l+1))%mo;else{int mid=(l+r)>>1;lazy[x<<1]=(lazy[x<<1]+lazy[x])%mo;lazy[(x<<1)+1]=(lazy[(x<<1)+1]+lazy[x])%mo;b[x]=(b[x]+1LL*lazy[x]*(r-l+1))%mo;lazy[x]=0;if (R<=mid) tree_find(x<<1,l,mid,L,R);else if (L>mid) tree_find((x<<1)+1,mid+1,r,L,R);else tree_find(x<<1,l,mid,L,mid),tree_find((x<<1)+1,mid+1,r,mid+1,R);} } void add(int p) {while (p!=0){tree_add(1,1,n,w[top[p]],w[p]);p=fa[top[p]];} } void find(int p) {while (p!=0){tree_find(1,1,n,w[top[p]],w[p]);p=fa[top[p]];} } int main() {n=getint(); q=getint();for (int i=2;i<=n;i++){p=getint()+1;fa[i]=p; link(p,i);}dep[1]=1; dfs1(1);dfs2(1,1); tot=0;for (int i=1;i<=q;i++){u=getint()+1; v=getint()+1; p=getint()+1;a[++tot].l=u-1; a[tot].f=-1; a[tot].wei=i; a[tot].w=p;a[++tot].l=v; a[tot].f=1; a[tot].wei=i; a[tot].w=p;}sort(a+1,a+1+tot,cmp);u=0; for (int i=1;i<=tot;i++){while (u<a[i].l) u++,add(u);sum=0; find(a[i].w);ans[a[i].wei]=(ans[a[i].wei]+1LL*sum*a[i].f+mo)%mo;}for (int i=1;i<=q;i++)printf("%lld\n",ans[i]);return 0; }

?

轉載于:https://www.cnblogs.com/xiaoqiang200015/p/6016006.html

總結

以上是生活随笔為你收集整理的bzoj3626:[LNOI2014]LCA的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。