bzoj 3551 kruskal重构树dfs序上的主席树
强制在线
kruskal重构树,每两点间的最大边权即为其lca的点权。
倍增找,dfs序对应区间搞主席树
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #define N 100005 #define M 500005 using namespace std; int l[2*N],r[2*N],cnt,num_cnt,val[2*N],num[2*N],ans; int sum[25*N],lon[25*N],ron[25*N]; int be[2*N],fa[2*N][21],dis[2*N][21],n,m,q,sz,oo,root[2*N]; int e=1,head[2*N]; bool vis[2*N]; struct edge{ int u,v,w,next; }ed[M],a[M]; bool cmp1(edge a,edge b){return a.w<b.w;} void add(int u,int v,int w){ ed[e].u=u; ed[e].v=v; ed[e].w=w; ed[e].next=head[u]; head[u]=e++; } int find(int x){ if(x==be[x])return x; be[x]=find(be[x]); return be[x]; } void Kruskal(){ sort(a+1,a+m+1,cmp1); for(int i=1;i<=m;++i){ int u=a[i].u,v=a[i].v; u=find(u); v=find(v); if(u!=v){ be[u]=be[v]=++n; fa[u][0]=fa[v][0]=n; dis[u][0]=dis[v][0]=a[i].w; add(n,u,a[i].w); add(n,v,a[i].w); } } } void insert(int p,int &rt,int l,int r,int x){ rt=++sz; sum[rt]=sum[p]+1; if(l==r) return; lon[rt]=lon[p]; ron[rt]=ron[p]; int mid=(l+r)>>1; if(x<=mid) insert(lon[p],lon[rt],l,mid,x); else insert(ron[p],ron[rt],mid+1,r,x); } void dfs(int x){ for(int i=1;i<=20;i++){ fa[x][i]=fa[fa[x][i-1]][i-1]; dis[x][i]=max(dis[x][i-1],dis[fa[x][i-1]][i-1]); } l[x]=++cnt; if(x<=oo) insert(root[cnt-1],root[cnt],1,num_cnt,val[x]); else root[cnt]=root[cnt-1]; for(int i=head[x];i;i=ed[i].next) dfs(ed[i].v); r[x]=cnt; } int query(int L,int R,int k){ L=root[L]; R=root[R]; if(k>sum[R]-sum[L]) return -1; int x=1,y=num_cnt; while(x<y){ int mid=(x+y)>>1; int tmp=sum[ron[R]]-sum[ron[L]]; if(tmp>=k){x=mid+1;L=ron[L];R=ron[R];} else{k-=tmp;y=mid;L=lon[L];R=lon[R];} } return num[x]; } void print(int x,int l,int r){ if(!x) return; printf("x==%d l==%d r==%d sum==%d\n",x,l,r,sum[x]); int mid=(l+r)>>1; print(lon[x],l,mid); print(ron[x],mid+1,r); } int main() { //freopen("3545.in","r",stdin); //freopen("3545.out","w",stdout); int u,v,w,x,k; scanf("%d%d%d",&n,&m,&q); oo=n; for(int i=1;i<=n;i++){ scanf("%d",&val[i]); num[i]=val[i]; } sort(num+1,num+n+1); num_cnt=unique(num+1,num+n+1)-num-1; for(int i=1;i<=n;i++) val[i]=lower_bound(num+1,num+num_cnt+1,val[i])-num; for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w); for(int i=1;i<=2*n;++i)be[i]=i; Kruskal(); memset(vis,0,sizeof vis); for(int i=n;i>=1;--i)if(!l[i])dfs(i); while(q--){ scanf("%d%d%d",&v,&x,&k); if(ans!=-1){v^=ans;x^=ans;k^=ans;} for(int i=20;~i;i--) if(dis[v][i]<=x&&fa[v][i]) v=fa[v][i]; ans=query(l[v]-1,r[v],k); printf("%d\n",ans); } return 0; }
人生如梦亦如幻 朝如晨露暮如霞。