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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【树链剖分】LCA(P4211)

發布時間:2023/12/3 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【树链剖分】LCA(P4211) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

P4211


題目大意

給你一棵樹,有m次詢問,每次詢問要回答∑i=lrdep[lca(x,i)]\sum_{i=l}^rdep[lca(x,i)]i=lr?dep[lca(x,i)]


解題思路

把用差分把問題分開,離線做

考慮樹鏈剖分,對于每個點維護輕兒子的貢獻,即輕子樹的大小乘dep[x]

每次查詢對于重鏈中到達的第一個點,計算子樹大小再減去上個子樹大小(計算過的),然后乘上dep[x],重鏈上其他點直接貢獻求和


code

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define wyc 201314 #define N 50050 using namespace std; ll n,m,x,y,z,w,qw,ww,tot,h[N],hs[N],sz[N],fa[N],ans[N],dep[N],top[N],dfn[N],low[N]; struct rec {ll to,nx; }e[N]; struct node {node(ll qq=0,ll xx=0,ll yy=0,ll gg=0){q=qq,x=xx,y=yy,g=gg;}ll q,x,y,g; }q[N<<1]; void add(ll x,ll y) {e[++tot].to=y;e[tot].nx=h[x];h[x]=tot;return; } void dfs1(ll x) {sz[x]=1;for(ll i=h[x];i;i=e[i].nx){ll y=e[i].to;dep[y]=dep[x]+1;fa[y]=x;dfs1(y);sz[x]+=sz[y];if(sz[y]>sz[hs[x]])hs[x]=y;}return; } void dfs2(ll x,ll anc) {dfn[x]=++w;top[x]=anc;if(hs[x])dfs2(hs[x],anc);for(ll i=h[x];i;i=e[i].nx){ll y=e[i].to;if(y!=hs[x])dfs2(y,y);}low[x]=w;return; } bool cmp(node a,node b) {return a.x<b.x; } struct Tree {#define ls x*2#define rs x*2+1ll s[N<<5],sz[N<<5];void push_up(ll x){s[x]=s[ls]+s[rs];sz[x]=sz[ls]+sz[rs];return;}void add(ll x,ll l,ll r,ll y,ll z,ll zz){if(l==r){s[x]+=z;sz[x]+=zz;return;}ll mid=l+r>>1;if(y<=mid)add(ls,l,mid,y,z,zz);else add(rs,mid+1,r,y,z,zz);push_up(x);return;}ll ask(ll x,ll L,ll R,ll l,ll r){if(L==l&&R==r)return s[x];ll mid=L+R>>1;if(r<=mid)return ask(ls,L,mid,l,r);else if(l>mid)return ask(rs,mid+1,R,l,r);else return ask(ls,L,mid,l,mid)+ask(rs,mid+1,R,mid+1,r);}ll asksz(ll x,ll L,ll R,ll l,ll r){if(L==l&&R==r)return sz[x];ll mid=L+R>>1;if(r<=mid)return asksz(ls,L,mid,l,r);else if(l>mid)return asksz(rs,mid+1,R,l,r);else return asksz(ls,L,mid,l,mid)+asksz(rs,mid+1,R,mid+1,r);} }T; void add(ll x) {T.add(1,1,n,dfn[x],0,1);while(x){T.add(1,1,n,dfn[x],dep[x],0);x=fa[top[x]];}return; } ll ask(ll x) {ll lst=0,sum=0;while(x){sum+=(T.asksz(1,1,n,dfn[x],low[x])-lst)*dep[x];//子樹內的點都到該點if(top[x]!=x)sum+=T.ask(1,1,n,dfn[top[x]],dfn[fa[x]]);//直接計算貢獻lst=T.asksz(1,1,n,dfn[top[x]],low[top[x]]);//上一個子樹的大小x=fa[top[x]];}return sum; } int main() {scanf("%lld%lld",&n,&m);for(ll i=2;i<=n;++i){scanf("%lld",&x);x++;add(x,i);}dep[1]=1;dfs1(1);dfs2(1,1);for(ll i=1;i<=m;++i){scanf("%lld%lld%lld",&x,&y,&z);x++,y++,z++;q[++qw]=node(i,x-1,z,-1);q[++qw]=node(i,y,z,1);}sort(q+1,q+1+qw,cmp);ww=1;while(ww<=qw&&q[ww].x<=0)ww++;for(ll i=1;i<=n;++i){add(i);while(ww<=qw&&q[ww].x<=i)ans[q[ww].q]+=ask(q[ww].y)*q[ww].g,ww++;}for(ll i=1;i<=m;++i)printf("%lld\n",ans[i]%wyc);return 0; }

總結

以上是生活随笔為你收集整理的【树链剖分】LCA(P4211)的全部內容,希望文章能夠幫你解決所遇到的問題。

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