hdu 3804(树链剖分+线段树)

来源:互联网 发布:恒生数据 编辑:程序博客网 时间:2024/06/05 04:16

题意:给出一棵树,Q个询问x,w,x到1的路径上不超过w的最长边是多少。

思路:题目读完了就知道用熟练剖分处理,然后可以用线段树求,线段树学的不是很好,就问了lyf怎么处理数据,他说把所有的询问按照权值的大小排序,边的大小也按权值排序,然后对每个询问把小于等于该权值的边加到树上就可以了。







#pragma comment(linker, "/STACK:10240000000000,10240000000000")#include<stdio.h>#include<stdlib.h>#include<string.h>const int N=101000;const int inf=0x3fffffff;struct edge{int st,ed,w,next;}e[N*2];struct node{int x,id,w,mw;}P[N],Q[N];int cmp(void const *a,void const *b){node *c,*d;c=(node *)a;d=(node *)b;return c->w-d->w;}int amp(void const *a,void const *b){node *c,*d;c=(node *)a;d=(node *)b;return c->id-d->id;}int max(int a,int b){if(a>b)return a;return b;}int head[N],father[N],son[N],sz[N],dep[N],num,cot[N],idx,ti[N],top[N],ans;void addedge(int x,int y,int w){e[num].st=x;e[num].ed=y;e[num].w=w;e[num].next=head[x];head[x]=num++;e[num].st=y;e[num].ed=x;e[num].w=w;e[num].next=head[y];head[y]=num++;}//***************树链剖分********************void find_son(int u){int i,v;son[u]=0;sz[u]=1;for(i=head[u];i!=-1;i=e[i].next){v=e[i].ed;if(v==father[u])continue;father[v]=u;dep[v]=dep[u]+1;cot[v]=e[i].w;find_son(v);sz[u]+=sz[v];if(sz[son[u]]<sz[v])son[u]=v;}}void find_time(int u,int fa){int i,v;top[u]=fa;ti[u]=idx++;P[ans].id=ti[u];//在线段树中的序号P[ans++].w=cot[u];//权值if(son[u]!=0)find_time(son[u],top[u]);for(i=head[u];i!=-1;i=e[i].next){v=e[i].ed;if(v==son[u]||v==father[u])continue;find_time(v,v);}}//************线段树************************struct Tree{int L,R,mw;}T[N*6];void buildTree(int L,int R,int id){T[id].L=L;T[id].R=R;T[id].mw=-inf;if(L==R)return ;int mid=(L+R)>>1,li=id<<1,ri=li|1;buildTree(L,mid,li);buildTree(mid+1,R,ri);}void insertTree(int x,int w,int id){if(T[id].L==T[id].R){T[id].mw=w;return ;}int mid=(T[id].L+T[id].R)>>1,li=id<<1,ri=li|1;if(x<=mid)insertTree(x,w,li);else insertTree(x,w,ri);T[id].mw=max(T[li].mw,T[ri].mw);}int find(int L,int R,int id){if(T[id].L==L&&T[id].R==R)return T[id].mw;int mid=(T[id].L+T[id].R)>>1,li=id<<1,ri=li|1;if(R<=mid)return find(L,R,li);else if(L>mid)return find(L,R,ri);else return max(find(L,mid,li),find(mid+1,R,ri));}int lca(int x,int y,int w){int Max=-1;while(dep[top[y]]>dep[top[x]]){Max=max(Max,find(ti[top[y]],ti[y],1));y=father[top[y]];}if(x!=y)  Max=max(Max,find(ti[x],ti[y],1));return Max;}int main(){int i,n,m,x,y,w,j,t;scanf("%d",&t);while(t--){memset(head,-1,sizeof(head));num=0;scanf("%d",&n);for(i=1;i<n;i++){scanf("%d%d%d",&x,&y,&w);addedge(x,y,w);}father[1]=0;sz[0]=0;dep[1]=1;cot[1]=0;find_son(1);idx=1;ans=0;find_time(1,1);buildTree(1,n,1);qsort(P,n,sizeof(P[0]),cmp);scanf("%d",&m);for(i=0;i<m;i++){scanf("%d%d",&Q[i].x,&Q[i].w);Q[i].id=i;}qsort(Q,m,sizeof(Q[0]),cmp);for(i=0,j=1;i<m;i++){while(P[j].w<=Q[i].w&&j<=n)//加边{insertTree(P[j].id,P[j].w,1);j++;}Q[i].mw=lca(1,Q[i].x,Q[i].w);//查找最大值}qsort(Q,m,sizeof(Q[0]),amp);for(i=0;i<m;i++){printf("%d\n",Q[i].mw);}}return 0;}