【JZOJ4587】Snow的追寻
来源:互联网 发布:js获取ios系统版本 编辑:程序博客网 时间:2024/06/10 20:19
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); }}
1 0
- 【JZOJ4587】Snow的追寻
- 【JZOJ4587】Snow的追寻 题解
- Snow的追寻
- Snow的追寻
- 【JZOJ 4587】Snow的追寻
- 【JZOJ 4587】 Snow的追寻
- (jzoj snow的追寻)线段树维护树的直径
- 追寻迷失的自我
- 追寻我的梦
- 追寻人生的意义
- 追寻自己的宁静
- 追寻我的梦
- 追寻大学的理性
- 《追寻生命的意义》
- 追寻你的脚步
- 追寻,盛夏的花开
- 追寻
- 追寻
- RHEL7修改网卡命名规则为eth*
- vs2015 配置boost
- 多态笔记
- APP开发流程实例讲解-儒释道网络电台八天开发全程-界面美化并进一步优化排错
- C语言运算符优先级 之 快速记忆
- 【JZOJ4587】Snow的追寻
- js中nodeName nodeType nodeValue的用法和区别
- 浅析遗传算法
- mysql的group_concat 对应 oracle的wm_concat
- 在UIView中添加点击事件oc及swift
- FatMouse' Trade(贪心)
- xml之libxml2使用
- 使用冒泡对数组进行排序
- 《UML基础只是讲解》