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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

LNOI2014 LCA

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

題目鏈接:戳我

區間求和可以分成前綴和差分,所以我們可以把每次詢問的l,r差分成\([1,r]-[1,l-1]\)

對于每一組詢問,我們把\([l,r]\)內的每個點到根的鏈上都+1,然后x和根的鏈上的累加和就是LCA的深度總和了。

為什么呢?大家可以畫畫圖,就顯而易見了因為題目上說了LCA的深度為它到根結點的距離+1,那么從一個結點出發,給它到根結點的鏈上的節點累加1的時候,顯然是從LCA開始才會對詢問點產生貢獻的。而這個貢獻個就是從LCA開始,到根結點(包含),的點數,而這正等于題目中對LCA深度的定義。

然后這個問題就可以轉換成樹上區間加和,區間求和啦!這不就是樹連剖分的模板了嗎,顯然一個一個求出來是不現實的,所以我們要考慮一次求出來很多個。所以我們先把所有詢問都離線下來,然后我們按照pos從小到大排序,然后如果now==a[i].pos的時候,就可以累加給該詢問答案了。

具體的請看代碼吧 QAQ

#include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdio> #define MAXN 500010 #define mod 201314 using namespace std;int n,Q,tt,cnt,tot; int wt[MAXN],bit[MAXN],id[MAXN]; int head[MAXN<<1],fa[MAXN],topf[MAXN],dep[MAXN],top[MAXN],son[MAXN],siz[MAXN];struct Edge{int nxt,to;}edge[MAXN<<1]; struct Node{int v,sum,l,r,tag;}t[MAXN<<4]; struct Node2{int pos,num,flag;}a[MAXN]; struct Que{int ans1,ans2,x;}q[MAXN];inline bool cmp(struct Node2 x,struct Node2 y){return x.pos<y.pos;}inline void add(int from,int to){edge[++tt].nxt=head[from],edge[tt].to=to,head[from]=tt;}inline void dfs1(int x,int pre) {dep[x]=dep[pre]+1;siz[x]=1;int maxx=-1;for(int i=head[x];i;i=edge[i].nxt){int v=edge[i].to;if(v==pre) continue;dfs1(v,x);siz[x]+=siz[v];if(siz[v]>maxx) maxx=siz[x],son[x]=v;} }inline void dfs2(int x,int topf) {top[x]=topf;id[x]=++cnt;if(son[x]) dfs2(son[x],topf);for(int i=head[x];i;i=edge[i].nxt){int v=edge[i].to;if(v==fa[x]||v==son[x]) continue;dfs2(v,v);} }inline int ls(int x){return x<<1;}inline int rs(int x){return x<<1|1;}inline void push_up(int x){t[x].sum=(t[ls(x)].sum+t[rs(x)].sum)%mod;}inline void f(int x,int k) {int l=t[x].l,r=t[x].r;t[x].tag=(t[x].tag+k)%mod;t[x].sum=(t[x].sum+1ll*(r-l+1)*k%mod)%mod; }inline void push_down(int x) {if(t[x].tag){f(ls(x),t[x].tag);f(rs(x),t[x].tag);t[x].tag=0;} }inline void build(int x,int l,int r) {t[x].l=l,t[x].r=r;if(l==r){t[x].sum=0;return;}int mid=(l+r)>>1;build(ls(x),l,mid);build(rs(x),mid+1,r);push_up(x); }inline void update(int x,int ll,int rr,int k) {int l=t[x].l,r=t[x].r;if(ll<=l&&r<=rr) {f(x,k);return;}int mid=(l+r)>>1;push_down(x);if(ll<=mid) update(ls(x),ll,rr,k);if(mid<rr) update(rs(x),ll,rr,k);push_up(x); }inline int query(int x,int ll,int rr) {int l=t[x].l,r=t[x].r;if(ll<=l&&r<=rr) return t[x].sum;int mid=(l+r)>>1;push_down(x);int cur_ans=0;if(ll<=mid) cur_ans+=query(ls(x),ll,rr);if(mid<rr) cur_ans+=query(rs(x),ll,rr);return cur_ans; }inline void ADD(int x,int y) {while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);update(1,id[top[x]],id[x],1);x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);update(1,id[x],id[y],1); }inline int QUERY(int x,int y) {int cur_ans=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);cur_ans=(cur_ans+query(1,id[top[x]],id[x]))%mod;x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);cur_ans=(cur_ans+query(1,id[x],id[y]))%mod;return cur_ans; }int main() {#ifndef ONLINE_JUDGEfreopen("ce.in","r",stdin);#endifscanf("%d%d",&n,&Q);n--;for(int i=1;i<=n;i++){scanf("%d",&fa[i]);add(fa[i],i);}for(int i=1;i<=Q;i++){int l,r;scanf("%d%d%d",&l,&r,&q[i].x);a[++tot].pos=l-1,a[tot].num=i,a[tot].flag=0;a[++tot].pos=r,a[tot].num=i,a[tot].flag=1;}build(1,1,n+1);dfs1(0,0);dfs2(0,0);// for(int i=0;i<=n;i++) printf("fa[%d]=%d\n",i,fa[i]); puts("");// for(int i=0;i<=n;i++) printf("dep[%d]=%d\n",i,dep[i]); puts("");// for(int i=0;i<=n;i++) printf("son[%d]=%d\n",i,son[i]); puts("");// for(int i=0;i<=n;i++) printf("siz[%d]=%d\n",i,siz[i]); puts("");// for(int i=0;i<=n;i++) printf("top[%d]=%d\n",i,top[i]); puts("");// for(int i=0;i<=n;i++) printf("id[%d]=%d\n",i,id[i]);int now=-1;sort(&a[1],&a[tot+1],cmp);for(int i=1;i<=tot;i++){ while(a[i].pos>now){now++;ADD(now,0);}int maomao=a[i].num;if(a[i].flag==0) q[maomao].ans1=QUERY(q[maomao].x,0);if(a[i].flag==1) q[maomao].ans2=QUERY(q[maomao].x,0);}for(int i=1;i<=Q;i++)printf("%d\n",((q[i].ans2-q[i].ans1)%mod+mod)%mod);return 0; }

轉載于:https://www.cnblogs.com/fengxunling/p/10774514.html

總結

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

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