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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

P2633 Count on a tree

發布時間:2023/12/3 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P2633 Count on a tree 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

P2633 Count on a tree

題意:

給定一棵 n 個節點的樹,每個點有一個權值。有 m 個詢問,每次給你 u,v,k,你需要回答 u xor last 和 v 這兩個節點間第 k 小的點權。

其中last 是上一個詢問的答案,定義其初始為 0,即第一個詢問的 u 是明文。

題解:

很明顯,主席樹,而且強制在線(更是主席樹)
主席樹是維護了一個類似前綴和的數據結構,當要查詢線性區間[l,r]的第k小時,用第r個線段樹減第l-1個線段樹,得到的就是[l,r]之間的權值線段樹(因為主席樹維護的就是前綴和),然后直接用二分查找第k小就行
在本題中給了一個樹,問點u到點v之間的第k小,我們都知道樹上差分(應該都知道),我們利用樹上差分就可以得到u到v之間的數據
定義s[u]為從根節點到點u節點的主席樹,那么u到v之間的所有數值信息的主席樹就應該是:
s[u]+s[v]-s[lca[u,v]]-s[fa[lca(u,v)]]
因為需要lca所以要用到倍增,可以在dfs中插入每個點

代碼:

#include<bits/stdc++.h> using namespace std; #define N 100010 #define M 2000010 int read(){int ans=0,w=1;char c=getchar();while(c!='-'&&!isdigit(c))c=getchar();if(c=='-')w=-1,c=getchar();while(isdigit(c))ans=ans*10+c-'0',c=getchar();return ans*w; } int n,m,num,lastans=0,u,v,tot,cnt; struct Edge{int v,next;}E[N<<1]; int head[N],a[N],b[N],fa[N][32],dep[N]; int rt[M]={0},ls[M]={0},rs[M]={0},siz[M]={0}; void add(int u,int v){E[++tot]=(Edge){v,head[u]};head[u]=tot; } void modify(int &rt,int lastrt,int l,int r,int val){rt=++cnt;ls[rt]=ls[lastrt]; rs[rt]=rs[lastrt];siz[rt]=siz[lastrt]+1;if(l==r)return;int mid=l+r>>1;if(mid>=val)modify(ls[rt],ls[lastrt],l,mid,val);else modify(rs[rt],rs[lastrt],mid+1,r,val); } int query(int rt1,int rt2,int rt3,int rt4,int l,int r,int k){if(l==r)return l;int mid=(l+r)>>1;int tmp=siz[ls[rt1]]+siz[ls[rt2]]-siz[ls[rt3]]-siz[ls[rt4]];if(tmp>=k)return query(ls[rt1],ls[rt2],ls[rt3],ls[rt4],l,mid,k);else return query(rs[rt1],rs[rt2],rs[rt3],rs[rt4],mid+1,r,k-tmp); } void dfs(int u,int f){dep[u]=dep[f]+1;for(int i=head[u];i;i=E[i].next){int v=E[i].v;if(v==fa[u][0])continue;fa[v][0]=u;modify(rt[v],rt[u],1,num,a[v]);dfs(v,u);} } int Lca(int x,int y){if(dep[x]<dep[y])swap(x,y);int t=dep[x]-dep[y];for(int i=0;(1<<i)<=t;i++)if((1<<i)&t)x=fa[x][i];for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];if(x==y)return x;return fa[x][0]; } int main(){n=read();m=read();for(int i=1;i<=n;i++)b[i]=a[i]=read();sort(b+1,b+n+1);num=unique(b+1,b+n+1)-b;for(int i=1;i<n;i++){u=read();v=read();add(u,v);add(v,u);}for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+num+1,a[i])-b;modify(rt[1],rt[0],1,num,a[1]);dfs(1,0);int up=log2(n);for(int k=1;k<=up;k++)for(int i=1;i<=n;i++)fa[i][k]=fa[fa[i][k-1]][k-1];for(int i=1;i<=m;i++){u=read();v=read();int k=read();u^=lastans;int lca=Lca(u,v);int ans=b[query(rt[u],rt[v],rt[lca],rt[fa[lca][0]],1,num,k)];printf("%d\n",ans);lastans=ans;}return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

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

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