【JZOJ4587】Snow的追寻
2016-07-08 08:06
253 查看
Description
Solution
一道很裸的题目,51Nod上有一个加强版的叫树中最远点对。思路
有对子树限制的就想一想dfs序。然后在dfs序上建一个线段树每个点存储它表示的点集的最长距离和对应的两个点,合并的时候有六种情况,两个子树的两个点两两配对,然后再与这两个点的值比较,一共六种。最后查询的时候,限制的两棵子树在dfs序上,分成了三个区间,这三个区间分别询问就好了。
Code
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define fo(i,a,b) for(i=a;i<=b;i++) #define fod(i,a,b) for(i=a;i>=b;i--) #define rep(i,a) for(i=first[a];i;i=next[i]) using namespace std; const int maxn=100007; int first[maxn*2],next[maxn*2],last[maxn*2],num; int i,j,k,l,n,m,q,da,da1,mx,mx1,dfn,wei[maxn],p[maxn],hou[maxn]; int d[maxn],deep[maxn],f[maxn][20]; bool bz[maxn]; struct node{ int sum,yi,er; }t[maxn*3],ans; void add(int x,int y){ last[++num]=y;next[num]=first[x];first[x]=num; } void dfs(int x,int y){ int i; wei[x]=++dfn;p[dfn]=x;f[x][0]=y;deep[x]=deep[y]+1; rep(i,x){ if(last[i]!=y){ dfs(last[i],x); } } hou[x]=dfn; } int lca(int x,int y){ int i,z=0;if(deep[x]<deep[y])swap(x,y); fod(i,19,0)if(deep[f[x][i]]>deep[y])x=f[x][i]; if(deep[x]>deep[y])x=f[x][0]; fod(i,19,0)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; if(x!=y)return f[x][0];return x; } int ju(int x,int y){ if(!x||!y)return 0; int z=lca(x,y); return deep[x]+deep[y]-2*deep[z]; } void merge(node &x,node y,node z){ int a,b,c,d,e,f; a=ju(y.yi,z.yi);b=ju(y.yi,z.er);c=ju(y.er,z.yi);d=ju(y.er,z.er); e=max(a,max(b,max(c,d))); if(!(e-a))x.yi=y.yi,x.er=z.yi,x.sum=a;if(!(e-b))x.yi=y.yi,x.er=z.er,x.sum=b; if(!(e-c))x.yi=y.er,x.er=z.yi,x.sum=c;if(!(e-d))x.yi=y.er,x.er=z.er,x.sum=d; if(y.sum>x.sum)x.yi=y.yi,x.er=y.er,x.sum=y.sum; if(z.sum>x.sum)x.yi=z.yi,x.er=z.er,x.sum=z.sum; if(!x.sum)x.yi=x.er=0; } void build(int x,int l,int r){ if(l==r){ t[x].yi=t[x].er=p[l];return; } int mid=(l+r)/2; build(x*2,l,mid);build(x*2+1,mid+1,r); merge(t[x],t[x*2],t[x*2+1]); } void find(int x,int l,int r,int y,int z){ if(y>z)return; if(l==y&&r==z){ merge(ans,ans,t[x]);return; } int mid=(l+r)/2; if(z<=mid)find(x*2,l,mid,y,z); else if(y>mid)find(x*2+1,mid+1,r,y,z); else{ find(x*2,l,mid,y,mid); find(x*2+1,mid+1,r,mid+1,z); } } int main(){ freopen("snow.in","r",stdin); freopen("snow.out","w",stdout); scanf("%d%d",&n,&q); fo(i,1,n-1){ scanf("%d%d",&k,&l); add(k,l);add(l,k); } dfs(1,0); fo(j,1,19){ fo(i,1,n)f[i][j]=f[f[i][j-1]][j-1]; } build(1,1,n); for(;q;q--){ scanf("%d%d",&k,&l); if(k==1||l==1){ printf("0\n"); continue; } if(wei[k]>wei[l])swap(k,l); ans.sum=ans.yi=ans.er=0; find(1,1,n,1,wei[k]-1); find(1,1,n,hou[k]+1,wei[l]-1); if(hou[k]>=hou[l])find(1,1,n,hou[k]+1,n); else find(1,1,n,hou[l]+1,n); printf("%d\n",ans.sum); } }
相关文章推荐
- 让您的Xcode键字如飞
- C语言运算符优先级 之 快速记忆
- 多态笔记
- mysql基本知识学习
- RHEL7修改网卡命名规则为eth*
- [Codeforces232D]Fence
- 【JZOJ4585】Robert 的军队
- 每天坚持一件事,60天来我一直这么做【天鹅干货铺22】
- AuthorizeAttribute认证失败Redirect后依旧会进入Action
- 4通用Makefile编写
- Implement Queue using Stacks
- 一个简单的文件读写实例
- Party
- inline内联函数详解
- struts2---获得Sevlet对象的2*2种方法
- ArrayList中去除重复数据,以及去除重复的自定义对象
- EntityFramework中LINQ To SQL的lumbda表达式的错误应用
- 自由控制灰度或原色ImageView
- Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Result Maps collection already
- 烽火传递 dp+单调队列