Min Max Roads Lightoj 1162

来源:互联网 发布:大连理工网络教育官网 编辑:程序博客网 时间:2024/05/25 16:37
//模版http://goaheadtw.iteye.com/blog/1185446#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int maxn=200005;const int INF=10000000;struct Node{int v,w;int next;}edge[maxn];//节点的标号从1开始 struct Seg{int ls,rs;int l,r;int max,min;int mid(){return (l+r)>>1;}}node[maxn<<2];int ln,tr;//ln链的个数,tr是树的根节点int n,tot,cnt;//n节点个数,tot线段树节点个数,cnt边的个数int que[maxn],par[maxn],dep[maxn],root[maxn],head[maxn],seg[maxn];int st[maxn],ed[maxn],top[maxn],sons[maxn],id[maxn],rev[maxn];//que用于BFS,par记录父节点,dep记录节点的深度。 root[i]为链i的根节点,seg用于在链上建线段树,  //st[i],ed[i]分别为链i的左右端点,top[i]为链i的顶部的节点,sons[i]为节点i的儿子节点数//id[i]是节点i所属的链的标号,rev[i]表示i的父亲与i相连的的边或i与i的父亲相连的边void add(int u,int v,int w){edge[cnt].v=v;edge[cnt].w=w;edge[cnt].next=head[u];head[u]=cnt++;}int Max(int a,int b){return a>b?a:b;}int Min(int a,int b){return a>b?b:a;}void newSeg(int &id,int l,int r){node[tot].ls=node[tot].rs=-1;node[tot].l=l;node[tot].r=r;node[tot].max=-INF;node[tot].min=INF;id=tot++;}void push_up(int id){int ls=node[id].ls,rs=node[id].rs;node[id].max=Max(node[ls].max,node[rs].max);node[id].min=Min(node[ls].min,node[rs].min);}void build(int &id,int l,int r){//在剖分出来的链上构建线段树if(l>=r)return ;newSeg(id,l,r);if(l+1==r){node[id].max=seg[l];//seg[l]为落在这个线段树节点上的原树中的节点  node[id].min=seg[l];return ;}int mid=(l+r)>>1;build(node[id].ls,l,mid);build(node[id].rs,mid,r);push_up(id);}void initTree(){//初始化剖分树//确定父亲  int l,r,u,v,i;l=r=0;que[r++]=tr;par[tr]=-1;dep[tr]=0;while(l != r){u=que[l++];for(i=head[u];i!=-1;i=edge[i].next){v=edge[i].v;if(v!=par[u]){rev[v]=i;//rev[v]=i^1que[r++]=v;par[v]=u;dep[v]=dep[u]+1;}}} //计算子树大小 for(i=1;i<=n;i++){sons[i]=1;id[i]=-1;}for(i=r-1;i>=0;i--){u=que[i];if(par[u]>=0){sons[par[u]]+=sons[u];}}//剖分链l=r=0;que[r++]=tr;ln=tot=0;while(l!=r){u=que[l++];st[ln]=dep[u];//用节点的深度作为线段树中区间的左右标号  top[ln]=u;while(u>=0){id[u]=ln;ed[ln]=dep[u];int best=-1;for(i=head[u];i!=-1;i=edge[i].next){v=edge[i].v;if(v!=par[u]){if(best==-1 || best>=0 && sons[v]>=sons[best]){best=v;}}}if(best>=0){for(i=head[u];i!=-1;i=edge[i].next){v=edge[i].v;if(v!=par[u] && best!=v){que[r++]=v;}else if(best==v){seg[dep[u]]=edge[i].w;}}}u=best;}root[ln]=-1;build(root[ln],st[ln],ed[ln]);ln++;}}struct Q{int max,min;Q(int max=-INF,int min=INF):max(max),min(min){};};Q lqry(int id,int ql,int qr){Q ret,t1,t2;if(ql>=qr)return ret;if(ql<=node[id].l && node[id].r<=qr){ret.max=Max(node[id].max,ret.max);ret.min=Min(node[id].min,ret.min);return ret;}int mid=(node[id].l+node[id].r)>>1;if(ql<mid) t1=lqry(node[id].ls,ql,qr);if(qr>mid) t2=lqry(node[id].rs,ql,qr);ret.max=Max(t1.max,t2.max);ret.min=Min(t1.min,t2.min);return ret;}Q qry(int u,int v){//查询u和v之间的最大或最小值 Q ret,t1;while(id[u]!=id[v]){if(id[u]>id[v]){u^=v^=u^=v;}int b=id[v];t1=lqry(root[b],st[b],dep[v]);ret.max=Max(ret.max,edge[rev[top[b]]].w);ret.min=Min(ret.min,edge[rev[top[b]]].w);ret.max=Max(t1.max,ret.max);ret.min=Min(t1.min,ret.min);v=par[top[b]];}if(dep[u]>dep[v]){u^=v^=u^=v;}t1=lqry(root[id[u]],dep[u],dep[v]);ret.max=Max(t1.max,ret.max);ret.min=Min(t1.min,ret.min);return ret;}void init(){tr=1;  cnt=0;memset(head,-1,sizeof(head));}int get_val(){ int ret(0); char c; while((c=getchar())==' '||c=='\n'||c=='\r'); ret=c-'0'; while((c=getchar())!=' '&&c!='\n'&&c!='\r') ret=ret*10+c-'0'; return ret;}int main(){int T,m;int u,v,w;int i,j,k;scanf("%d",&T);for(int cas=1;cas<=T;cas++){init();scanf("%d",&n);for(i=1;i<n;i++){//scanf("%d%d%d",&u,&v,&w);u=get_val();v=get_val();w=get_val();add(u,v,w);add(v,u,w);}initTree();scanf("%d",&m);printf("Case %d:\n",cas);for(i=0;i<m;i++){scanf("%d%d",&u,&v);Q p=qry(u,v);printf("%d %d\n",p.min,p.max);}}return 0;}


 

原创粉丝点击