1. 程式人生 > >[BZOJ2588]Spoj 10628. Count on a tree

[BZOJ2588]Spoj 10628. Count on a tree

題意

給定一個有n個結點的樹,線上詢問兩個點之間路徑上第k大的點的點權是多少。

分析

其實剛開始看到這道題的想法是樹鏈剖分出log條鏈在同時在可持久化線段樹上查詢第k大。但是這樣寫起來並不優雅而且很難寫。
然後考慮每次其實相當於取出兩條點到某個祖先的鏈找第k大,所以這裡的可持久化線段樹可以不基於dfs序,而是直接用父親結點的線段樹。
然後這樣就只需要求一個lca,然後開始的時候建一棵可持久化線段樹即可。

code

//201806月09日 星期六 101617#include<bits/stdc++.h>
#define M 100005
using namespace std;
void read
(int &x){ x=0; char c=getchar(); for (;c<48;c=getchar()); for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48); } struct ed{ int x,nx; }e[M<<1]; int a[M],b[M],rt[M],fa[M],top[M],son[M],de[M],nx[M],ecnt=1,cnt[M]; void add(int x,int y){ e[ecnt]=(ed){y,nx[x]}; nx[x
]=ecnt++; } int ch(int l,int r,int x){ int mid; for (;l<=r;){ mid=(l+r)>>1; if (b[mid]==x)return mid; if (b[mid]<x)l=mid+1; else r=mid-1; } } struct Tree{ int tot,f[M*30],rs[M*30],ls[M*30]; void build(int l,int r,int &p){ p=++tot; if
(l==r)return; int mid=(l+r)>>1; build(l,mid,ls[p]); build(mid+1,r,rs[p]); } void build(int l,int r,int x,int lp,int &p){ p=++tot; ls[p]=ls[lp]; rs[p]=rs[lp]; f[p]=f[lp]+1; if (l==r){ return; } int mid=(l+r)>>1; if (x<=mid)build(l,mid,x,ls[lp],ls[p]); else build(mid+1,r,x,rs[lp],rs[p]); } int qu(int l,int r,int k,int p1,int p2,int p3,int p4){ if (l==r)return l; int sum=(f[ls[p1]]+f[ls[p2]]-f[ls[p3]]-f[ls[p4]]),mid=(l+r)>>1; if (sum>=k)return qu(l,mid,k,ls[p1],ls[p2],ls[p3],ls[p4]); else return qu(mid+1,r,k-sum,rs[p1],rs[p2],rs[p3],rs[p4]); } void pt(int l,int r,int p){ if (l==r){ printf("%d ",f[p]); return ; } int mid=(l+r)>>1; pt(l,mid,ls[p]); pt(mid+1,r,rs[p]); } }T; int tot; void dfs1(int f,int x){ fa[x]=f; cnt[x]=1; de[x]=de[f]+1; son[x]=0; for (int i=nx[x];i;i=e[i].nx)if (e[i].x!=f){ dfs1(x,e[i].x); cnt[x]+=cnt[e[i].x]; if (cnt[e[i].x]>cnt[son[x]])son[x]=e[i].x; } } void dfs2(int f,int x){ top[x]=f; T.build(1,tot,a[x],rt[fa[x]],rt[x]); if (son[x])dfs2(f,son[x]); for (int i=nx[x];i;i=e[i].nx)if(e[i].x!=fa[x]&&e[i].x!=son[x]){ dfs2(e[i].x,e[i].x); } } int lca(int x,int y){ for (;top[x]!=top[y];){ if (de[top[x]]>de[top[y]])x=fa[top[x]]; else y=fa[top[y]]; } if (de[x]<de[y])return x; return y; } int qu(int x,int y,int k){ int Lca=lca(x,y); return T.qu(1,tot,k,rt[x],rt[y],rt[Lca],rt[fa[Lca]]); } int main(){ // freopen("1.in","r",stdin); int n,m,i,x,y,res=0,k; read(n); read(m); for (i=1;i<=n;i++)read(a[i]),b[i]=a[i]; sort(b+1,b+n+1); tot=unique(b+1,b+n+1)-b-1; for (i=1;i<=n;i++)a[i]=ch(1,tot,a[i]); for (i=1;i<n;i++){ read(x); read(y); add(x,y); add(y,x); } T.build(1,tot,rt[0]); dfs1(0,1); dfs2(1,1); // for (i=1;i<=n;i++)printf("------%d-------\n",i),T.pt(1,tot,rt[i]),printf("\n"); for (;m--;){ read(x); read(y); read(k); x^=res; res=b[qu(x,y,k)]; printf("%d",res); if (m)puts(""); } return 0; }

其實是很裸的題?qwq我太弱了