[缩树 主席树] BZOJ 4539 [Hnoi2016]树
来源:互联网 发布:数据分析师培训机构 编辑:程序博客网 时间:2024/05/21 08:41
hnoi的大数据结构题
把每一个残基缩一下 变成一颗大树
每次新增
查询一下是在哪个残基上 这里要用主席树求子树第k大
然后记一下到fat的权值
然后就各种细节搞lca
#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++;}inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}inline void read(ll &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=100005;#define V G[p].vnamespace tree1{ struct edge{ int u,v,next; }G[N<<2]; int head[N],inum; inline void add(int u,int v,int p){ G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p; } inline void link(int u,int v){ add(u,v,++inum); add(v,u,++inum); } const int K=21; int fat[N][K],depth[N]; int clk,pre[N],bac[N],size[N]; inline void dfs(int u,int fa){ pre[u]=++clk; bac[clk]=u; size[u]=1; fat[u][0]=fa; depth[u]=depth[fa]+1; for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1]; for (int p=head[u];p;p=G[p].next) if (V!=fa)dfs(V,u),size[u]+=size[V]; } inline int LCA(int u,int v){ if (depth[u]<depth[v]) swap(u,v); for (int k=K-1;~k;k--) if ((depth[u]-depth[v])&(1<<k)) u=fat[u][k]; if (u==v) return u; for (int k=K-1;~k;k--) if (fat[u][k]!=fat[v][k]) u=fat[u][k],v=fat[v][k]; return fat[v][0]; } inline int Dist(int u,int v){ return depth[u]+depth[v]-2*depth[LCA(u,v)]; }}namespace tree2{ struct edge{ int u,v,w,next; }G[N<<2]; int head[N],inum; inline void add(int u,int v,int w,int p){ G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p; } inline void link(int u,int v,int w){ add(u,v,w,++inum); add(v,u,w,++inum); } const int K=21; int fat[N][K],depth[N]; ll dis[N]; int clk,pre[N],bac[N],size[N]; inline void dfs(int u,int fa){ pre[u]=++clk; bac[clk]=u; size[u]=1; fat[u][0]=fa; depth[u]=depth[fa]+1; for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1]; for (int p=head[u];p;p=G[p].next) if (V!=fa)dis[V]=dis[u]+G[p].w,dfs(V,u),size[u]+=size[V]; } inline int LCA(int u,int v){ if (depth[u]<depth[v]) swap(u,v); for (int k=K-1;~k;k--) if ((depth[u]-depth[v])&(1<<k)) u=fat[u][k]; if (u==v) return u; for (int k=K-1;~k;k--) if (fat[u][k]!=fat[v][k]) u=fat[u][k],v=fat[v][k]; return fat[v][0]; } inline int Fat(int u,int lca){ for (int k=K-1;~k;k--) if (depth[fat[u][k]]>depth[lca])u=fat[u][k]; return u; } inline ll Dist(int u,int v){ return dis[u]+dis[v]-2*dis[LCA(u,v)]; }}namespace Seg{ int root[N],ncnt; int ls[N*21],rs[N*21],sum[N*21]; inline void Add(int &x,int y,int l,int r,int t){ if (!x) x=++ncnt; int mid=(l+r)>>1; if (l==r){ sum[x]=sum[y]+1; return; } if (t<=mid) Add(ls[x],ls[y],l,mid,t),rs[x]=rs[y]; else Add(rs[x],rs[y],mid+1,r,t),ls[x]=ls[y]; sum[x]=sum[ls[x]]+sum[rs[x]]; } inline int Query(int x,int y,int l,int r,int k){ if (l==r) return l; int mid=(l+r)>>1; if (k<=sum[ls[y]]-sum[ls[x]]) return Query(ls[x],ls[y],l,mid,k); else return Query(rs[x],rs[y],mid+1,r,k-(sum[ls[y]]-sum[ls[x]])); }}int n,m,Q;inline void Init(){ using namespace tree1; for (int i=1;i<=n;i++) Seg::Add(Seg::root[i],Seg::root[i-1],1,n,bac[i]);}inline int Query(int u,int k){ using namespace tree1; return Seg::Query(Seg::root[pre[u]-1],Seg::root[pre[u]+size[u]-1],1,n,k);}int fcnt,ft[N],ff[N];ll fl[N],fr[N];inline int belong(ll idx){ return lower_bound(fr+1,fr+fcnt+1,idx)-fr;}inline void Link(int a,ll b){ int rt=belong(b); int ch=Query(ft[rt],b-fl[rt]+1); ++fcnt; ft[fcnt]=a; fl[fcnt]=fr[fcnt-1]+1; fr[fcnt]=fr[fcnt-1]+tree1::size[a]; ff[fcnt]=ch; tree2::link(rt,fcnt,tree1::depth[ch]-tree1::depth[ft[rt]]+1);}inline ll Dis(ll u){ int rt=belong(u); int ch=Query(ft[rt],u-fl[rt]+1); return tree2::dis[rt]+tree1::depth[ch]-tree1::depth[ft[rt]];}inline void Solve(ll a,ll b){ ll ret=Dis(a)+Dis(b),tem=0; int rta=belong(a),rtb=belong(b),lca=tree2::LCA(rta,rtb); if (lca==rta && lca==rtb){ int cha=Query(ft[rta],a-fl[rta]+1),chb=Query(ft[rtb],b-fl[rtb]+1); int t=tree1::LCA(cha,chb); tem+=tree2::dis[lca]; tem+=tree1::depth[t]-tree1::depth[ft[lca]]; } else if (lca==rta || lca==rtb){ if (rtb==lca) swap(rtb,rta),swap(a,b); int cha=Query(ft[rta],a-fl[rta]+1),chb=tree2::Fat(rtb,lca); int t=tree1::LCA(cha,ff[chb]); tem+=tree2::dis[lca]; tem+=tree1::depth[t]-tree1::depth[ft[lca]]; }else{ int cha=tree2::Fat(rta,lca),chb=tree2::Fat(rtb,lca); int t=tree1::LCA(ff[cha],ff[chb]); tem+=tree2::dis[lca]; tem+=tree1::depth[t]-tree1::depth[ft[lca]]; } printf("%lld\n",ret-2*tem);}int main(){ int iu,iv; ll ia,ib; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); read(Q); for (int i=1;i<n;i++){ read(iu); read(iv); tree1::link(iu,iv); } tree1::dfs(1,0); Init(); fcnt=1; fl[1]=1; fr[1]=n; ft[1]=1; for (int i=1;i<=m;i++){ read(iu); read(ib); Link(iu,ib); } tree2::dfs(1,0); while (Q--){ read(ia); read(ib); Solve(ia,ib); } return 0;}
0 0
- [缩树 主席树] BZOJ 4539 [Hnoi2016]树
- bzoj 4539: [Hnoi2016]树 主席树&lca
- bzoj 4539: [Hnoi2016]树(缩点+主席树+lca)
- bzoj 4539 [Hnoi2016]树 主席树 倍增lca
- 【BZOJ 4539】[Hnoi2016]树 倍增lca+主席树
- BZOJ 4539: [Hnoi2016]树
- bzoj 4539: [Hnoi2016]树
- 【bzoj4539】【HNOI2016】【树】【主席树】
- bzoj 3932(主席树)
- BZOJ 2588 主席树
- [BZOJ4539][Hnoi2016]树(dfs序+主席树+lca)
- [BZOJ4539][Hnoi2016]树(倍增+LCA+主席树)
- bzoj 4538: [Hnoi2016]网络 树链剖分+线段树
- 4539: [Hnoi2016]树
- bzoj 4539 HNOI 2016 树 主席树
- [HNOI2016]树
- [HNOI2016] 树
- 【BZOJ 2809】dispatching(主席树)
- position笔记
- AndroidStudio多渠道打包
- RTl8188EUS无线网卡驱动编译,支持master模式
- C# $字符串
- 关于iOS中的NSUserDefaults系统隐藏目录
- [缩树 主席树] BZOJ 4539 [Hnoi2016]树
- android studio 的工具device monitor显示出错(界面变灰)
- JFinal使用FreeMarker静态文件路径
- c++(16)编写自己的头文件
- HDU 2089 不要62 (经典的数位dp)
- C++ bitset类的使用与简介
- 02-线性结构2 一元多项式的乘法与加法运算 (20分)
- 用UglifyJS2合并压缩混淆JS代码
- windows服务注册 -- svn服务器开机自启