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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Distance on the tree(树上倍增+主席树+树上差分+lca)南昌网络赛

發布時間:2023/12/15 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Distance on the tree(树上倍增+主席树+树上差分+lca)南昌网络赛 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:南昌邀請賽網絡賽Distance on the tree
統計一條鏈上邊權小于k的邊數。
樹上差分,對于邊權來說,一條鏈上的邊的條數=sum[x]+sum[y]-2*sum[lca(x,y)]。
對于點權來說,點數=sum[x]+sum[y]-sum[lca(x,y)]-sum[fa[lca(x,y)]]。
在求祖先的時候,需要用到樹上倍增+lca。其余的就在主席樹上去找就好了。
代碼如下:

#include<bits/stdc++.h> #define ll long long using namespace std;const int maxx=1e5+100; struct node{int l;int r;int sum; }p[maxx*20]; int head[maxx<<1]; int dp[maxx][22]; int val[maxx]; int deep[maxx]; int root[maxx]; struct edge{int to,next,w; }e[maxx<<1]; int tot,n,m,len,ror; /*-------------事前準備--------------*/ inline int getid(int w) {return lower_bound(val+1,val+len+1,w)-val; } inline void init() {for(int i=0;i<=n;i++)for(int j=0;j<=20;j++) dp[i][j]=0;memset(head,-1,sizeof(head));tot=0;ror=0; } inline void add(int u,int v,int w) {e[tot].to=v,e[tot].next=head[u],e[tot].w=w,head[u]=tot++; } /*-------------主席樹--------------*/ inline void pushup(int cur) {p[cur].sum=p[p[cur].l].sum+p[p[cur].r].sum; } inline int build(int l,int r) {int cur=++ror;p[cur].sum=0;if(l==r) return cur;int mid=l+r>>1;p[cur].l=build(l,mid);p[cur].r=build(mid+1,r);return cur; } inline int update(int pos,int rot,int l,int r) {int cur=++ror;p[cur]=p[rot];if(l==r) {p[cur].sum++;return cur;}int mid=l+r>>1;if(pos<=mid) p[cur].l=update(pos,p[rot].l,l,mid);else p[cur].r=update(pos,p[rot].r,mid+1,r);pushup(cur);return cur; } inline int query(int lrot,int rrot,int frot,int l,int r,int sum) {if(r<=sum) return p[lrot].sum+p[rrot].sum-p[frot].sum*2;int mid=l+r>>1;int ret=p[p[lrot].l].sum+p[p[rrot].l].sum-p[p[frot].l].sum*2;if(sum<=mid) return query(p[lrot].l,p[rrot].l,p[frot].l,l,mid,sum);else return ret+query(p[lrot].r,p[rrot].r,p[frot].r,mid+1,r,sum); } /*-------------dfs---------------*/ inline void dfs(int u,int f) {deep[u]=deep[f]+1;dp[u][0]=f;for(int i=1;i<=20;i++){if(dp[u][i-1]) dp[u][i]=dp[dp[u][i-1]][i-1];else break;}for(int i=head[u];i!=-1;i=e[i].next){int to=e[i].to,w=e[i].w;if(to==f) continue;root[to]=update(getid(w),root[u],1,len);dfs(to,u);} } /*-----------lca-----------*/ inline int get_lca(int x,int y) {if(deep[x]<deep[y]) swap(x,y);int tmp=deep[x]-deep[y];for(int i=0;i<=20;i++){if(tmp&(1<<i)) x=dp[x][i];}if(x==y) return x;for(int i=20;i>=0;i--){if(dp[x][i]!=dp[y][i]){x=dp[x][i];y=dp[y][i];}}return dp[x][0]; } int main() {int x,y,w;while(~scanf("%d%d",&n,&m)){init();for(int i=1;i<n;i++){scanf("%d%d%d",&x,&y,&w);add(x,y,w);add(y,x,w);val[i]=w;}sort(val+1,val+n);len=unique(val+1,val+n)-val-1;root[0]=build(1,len);deep[0]=1;dfs(1,0);while(m--){scanf("%d%d%d",&x,&y,&w);int z=get_lca(x,y);w=upper_bound(val+1,val+len+1,w)-val-1;//在這里用upper_bound,這樣之后找出來的一定是小于等于w的值。if(w==0) printf("0\n");else printf("%d\n",query(root[x],root[y],root[z],1,len,w));}}return 0; }

努力加油a啊,(o)/~

總結

以上是生活随笔為你收集整理的Distance on the tree(树上倍增+主席树+树上差分+lca)南昌网络赛的全部內容,希望文章能夠幫你解決所遇到的問題。

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