BZOJ 4539: [Hnoi2016]树
2016-04-19 11:51
381 查看
md强行凑数据结构题,树剖+主席树,各种函数搞一大堆查询,然后其实就是求两点的lca。。。。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=100000+5; #define rep(i,l,r) for(int i=l;i<=r;i++) typedef long long ll; ll read(){ char ch=getchar();ll x=0,f=1; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct Edge{int to,next;}e[N<<1],g[N<<1]; int head ,cnt,last ,tot; void ins1(int u,int v){e[++cnt]=(Edge){v,head[u]};head[u]=cnt;} void insert1(int u,int v){ins1(u,v);ins1(v,u);} void ins2(int u,int v){g[++tot]=(Edge){v,last[u]};last[u]=tot;} void insert2(int u,int v){ins2(u,v);ins2(v,u);} int fa1 ,dep1 ,top1 ,son1 ,siz1 ,st ,ed ,dfn ,sz; void dfs1(int u){ dfn[st[u]=++sz]=u;siz1[u]=1; for(int i=head[u];i;i=e[i].next){ int v=e[i].to;if(v==fa1[u])continue; fa1[v]=u;dep1[v]=dep1[u]+1;dfs1(v); siz1[u]+=siz1[v];if(siz1[v]>siz1[son1[u]])son1[u]=v; } ed[u]=sz; } void dfs1(int u,int tp){ top1[u]=tp; if(son1[u])dfs1(son1[u],tp); for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(v!=fa1[u]&&v!=son1[u])dfs1(v,v); } } struct Node{ int lc,rc,w; }tr[N*20]; int node,root ; void build(int &o,int l,int r){ o=++node; if(l==r)return; int mid=l+r>>1; build(tr[o].lc,l,mid);build(tr[o].rc,mid+1,r); } void insert(int &o,int l,int r,int p){ tr[++node]=tr[o];o=node; tr[o].w++; if(l==r)return; int mid=l+r>>1; if(p<=mid)insert(tr[o].lc,l,mid,p); else insert(tr[o].rc,mid+1,r,p); } int query(int x,int y,int l,int r,int k){ if(l==r)return l; int mid=l+r>>1; int sum=tr[tr[y].lc].w-tr[tr[x].lc].w; if(k<=sum) return query(tr[x].lc,tr[y].lc,l,mid,k); else return query(tr[x].rc,tr[y].rc,mid+1,r,k-sum); } int rank(int x,int y,int l,int r,int k){ if(l==r)return tr[y].w-tr[x].w; int mid=l+r>>1; if(k<=mid)return rank(tr[x].lc,tr[y].lc,l,mid,k); else return rank(tr[x].rc,tr[y].rc,mid+1,r,k)+tr[tr[y].lc].w-tr[tr[x].lc].w; } int query(int u,int k){ return query(root[st[u]-1],root[ed[u]],1,sz,k); } int rank(int u,int k){ return rank(root[st[u]-1],root[ed[u]],1,sz,k); } int fa2 ,dep2 ,siz2 ,son2 ,top2 ,cost ; ll depth ; void dfs2(int u){ siz2[u]=1; for(int i=last[u];i;i=g[i].next){ int v=g[i].to;if(v==fa2[u])continue; dep2[v]=dep2[u]+1;fa2[v]=u;depth[v]=depth[u]+cost[v];dfs2(v); siz2[u]+=siz2[v];if(siz2[v]>siz2[son2[u]])son2[u]=v; } } void dfs2(int u,int tp){ top2[u]=tp; if(son2[u])dfs2(son2[u],tp); for(int i=last[u];i;i=g[i].next){ int v=g[i].to; if(v!=son2[u]&&v!=fa2[u])dfs2(v,v); } } ll size ; int n,m,now; int belong(ll id){ int l=1,r=now; while(l<=r){ int mid=l+r>>1; if(size[mid]<id)l=mid+1; else r=mid-1; } return l-1; } int lca1(int u,int v){ while(top1[u]!=top1[v]){ if(dep1[top1[u]]<dep1[top1[v]])swap(u,v); u=fa1[top1[u]]; } return dep1[u]<dep1[v]?u:v; } ll li ; int rt ; ll lca2(ll u,ll v){ int x=belong(u),y=belong(v); while(top2[x]!=top2[y]){ if(dep2[top2[x]]<dep2[top2[y]])swap(x,y),swap(u,v); x=top2[x];u=li[x];x=fa2[x]; } if(x!=y){ if(dep2[x]>dep2[y])swap(x,y),swap(u,v); y=x;v=li[son2[y]]; } return size[x]+rank(rt[x],lca1(query(rt[x],u-size[x]),query(rt[y],v-size[y]))); } ll dep(ll u){ int x=belong(u); return depth[x]+dep1[query(rt[x],u-size[x])]-dep1[rt[x]]; } ll dist(ll u,ll v){ return dep(u)+dep(v)-2*dep(lca2(u,v)); } int main(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); int q;n=read();m=read();q=read(); rep(i,2,n){int u,v;u=read();v=read();insert1(u,v);} dfs1(1);dfs1(1,1); build(root[0],1,sz); rep(i,1,sz){ root[i]=root[i-1]; insert(root[i],1,sz,dfn[i]); } rt[1]=1;m++;now=1; rep(i,2,m){ rt[i]=read();li[i]=read();size[i]=size[i-1]+siz1[rt[i-1]]; int x=belong(li[i]); insert2(i,x); cost[i]=dep1[query(rt[x],li[i]-size[x])]-dep1[rt[x]]+1; now++; } dfs2(1);dfs2(1,1); while(q--){ ll u,v;u=read();v=read(); printf("%lld\n",dist(u,v)); } return 0; }
相关文章推荐
- java的Socket连接简单案例
- Linux 下java 中添加c++
- 区块链技术
- 多线程学习05-线程状态
- CALayer的介绍
- java大数据学习笔记(二) 线程池与应用
- C++学习笔记十五 - C++的类
- hashCode与equals源码分析与应用
- mybatis重复扫描package的问题
- js 小数点前面的0不显示
- redo和undo的区别
- 笔记sql语句
- js,javascript四舍五入round
- 南京理工大学第八届程序设计大赛count_prime
- js下读取或者设置input中的value值
- 欢迎使用CSDN-markdown编辑器
- 快速向表中插入大量数据Oracle中append与Nologging
- php使用 ajax操作购物车
- JavaScript replace() 方法
- 什么是JSON