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;}
- hdu 3804(树链剖分+线段树)
- hdu 3804 树链剖分+线段树
- hdu 3966 (树链剖分+线段树)
- hdu 3966 树链剖分+线段树
- hdu 5029树链剖分+线段树
- Hdu 3804 Query on a tree 树链剖分+线段树
- HDU-3966 (树链剖分+线段树)
- hdu 5029 Relief grain (树链剖分+线段树)
- hdu 5029 Relief grain(树链剖分+线段树)
- hdu-3966(树链剖分+线段树)
- HDU-5242 Game (贪心&&树链剖分&&线段树)
- 【HDU 5221】 Occupation 【树链剖分+线段树】
- Hdu 5405 Sometimes Naive 树链剖分+线段树
- HDU 5029Relief grain(树链剖分+线段树)
- hdu 1754 线段树
- hdu 1754 线段树
- HDU 1698 线段树
- hdu 1754 线段树
- 栈
- 学写controller
- 黑马程序员_源自梦想 java --类、对象
- 详细解析sizeof和结构体对齐
- iptables的详细介绍及配置方法
- hdu 3804(树链剖分+线段树)
- Android中用Spannable在TextView中设置超链接、颜色、字体
- 各种input相关操作
- 数列极差问题
- XeLaTeX+xeCJK中文字体设置
- Android 焦点问题
- android EditText 自动滚动条并显示最新内容 .
- Ubuntu13.10几分钟自动断网问题(已解决)
- 批量提取文件名bat doc命令