hdu 4123-Bob’s Race 2011福州赛
http://acm.hdu.edu.cn/showproblem.php?pid=4123
哥的心都碎了,现场赛不知道什么原因竟然连long long 都没注意。菜鸟就是菜鸟,明年继续努力吧。
题意:
n个点的树,每个点有一个人,每个人会跑到离自己初始点距离最远的点上,
这个距离为distance[i]。给你m个查询,对于每个查询Q,找一段连续编号的人,
比如[left,right],满足 max( distance[i] i∈[left,right] ) – min( distance[i] i∈[left,right] ) ≤ Q,
并且使得length=right-left+1要最大,求这个最大的length
题目看似有点难,其实分析清楚了一步步来还是比较简单的。
首先 要找 “每个人会跑到离自己初始点距离最远的点上”——dis[i]
这个用树形dp很简单可以解决,保存两个从儿子走能走的最长距离和第二长距离
在第二遍搜的时候如果你搜到得儿子是最长的距离的那个,很显然你要拉第二长距离的儿子过来。这个还是自己理解吧....
中间 rmq
后面是 单调队列,保证答案只会变大。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<vector> 4 using namespace std; 5 #include<algorithm> 6 #include<string> 7 #define N 50010 8 #define M 510 9 #define inf 200000000 10 int w[N],edge,id[N],an[M]; 11 __int64 dp[N][2],dis[N]; 12 struct qq{ 13 int id; 14 __int64 l; 15 }q[M]; 16 bool cmp(const qq &a,const qq &b){ 17 return a.l<b.l; 18 } 19 struct node{ 20 int v,next; 21 __int64 l; 22 }e[N*2]; 23 void add(int u,int v,__int64 l){ 24 e[edge].v=v; 25 e[edge].l=l; 26 e[edge].next=w[u]; 27 w[u]=edge++; 28 } 29 void dfs1(int u,int no){ 30 for(int i=w[u];i!=-1;i=e[i].next){ 31 int v=e[i].v; 32 if(v!=no){ 33 dfs1(v,u); 34 if(dp[v][0]+e[i].l>dp[u][0]){ 35 dp[u][1]=dp[u][0]; 36 id[u]=v,dp[u][0]=dp[v][0]+e[i].l; 37 } 38 else if(dp[v][0]+e[i].l>dp[u][1]) dp[u][1]=dp[v][0]+e[i].l; 39 } 40 } 41 } 42 43 44 void dfs2(int u,int no,__int64 l){ 45 dis[u]=max(l,dp[u][0]); 46 for(int i=w[u];i!=-1;i=e[i].next){ 47 int v=e[i].v; 48 if(v!=no){ 49 if(v==id[u]) dfs2(v,u,max(l,dp[u][1])+e[i].l); 50 else dfs2(v,u,dis[u]+e[i].l); 51 } 52 } 53 } 54 55 int dp_max[N][20],dp_min[N][20]; 56 __int64 p[20]; 57 int max_id(int x,int y){ 58 return dis[x]>dis[y]?x:y; 59 } 60 int min_id(int x,int y){ 61 return dis[x]>dis[y]?y:x; 62 } 63 int log(int x){ 64 int i=0; 65 while(p[i]<=x) i++; 66 return i-1; 67 } 68 int get_max_id(int x,int y){ 69 int t=log(y-x+1); 70 return max_id(dp_max[x][t],dp_max[y-p[t]+1][t]); 71 } 72 int get_min_id(int x,int y){ 73 int t=log(y-x+1); 74 return min_id(dp_min[x][t],dp_min[y-p[t]+1][t]); 75 } 76 77 __int64 get_min(int x,int y){ 78 return dis[get_min_id(x,y)]; 79 } 80 __int64 get_max(int x,int y){ 81 return dis[get_max_id(x,y)]; 82 } 83 void RMQ(int n){ 84 int i,j,l=n,t=0; 85 p[0]=1; 86 for(i=1;i<18;i++) 87 p[i]=p[i-1]<<1; 88 t=log(n); 89 for(i=1;i<=n;i++) 90 dp_max[i][0]=dp_min[i][0]=i; 91 for(i=1;i<=t;i++){ 92 l=n-p[i]+1; 93 for(j=1;j<=l;j++){ 94 dp_max[j][i]=max_id(dp_max[j][i-1],dp_max[j+p[i-1]][i-1]); 95 dp_min[j][i]=min_id(dp_min[j][i-1],dp_min[j+p[i-1]][i-1]); 96 } 97 } 98 } 99 100 int main(){ 101 //#ifndef ONLINE_JUDGE 102 // freopen("C:\\Users\\Slon\\Desktop\\in.txt","r",stdin); 103 // freopen("C:\\Users\\Slon\\Desktop\\out.txt","w",stdout); 104 //#endif 105 int n,m,a,b; 106 __int64 c; 107 while(scanf("%d%d",&n,&m)){ 108 if(!n&&!m) break; 109 edge=0; 110 memset(w,-1,sizeof(int)*(n+1)); 111 for(int i=1;i<n;++i){ 112 scanf("%d%d%I64d",&a,&b,&c); 113 add(a,b,c); 114 add(b,a,c); 115 } 116 memset(dis,0,sizeof(__int64)*(n+1)); 117 memset(dp,0,sizeof(dp)); 118 dfs1(1,1); 119 dfs2(1,1,0); 120 121 RMQ(n); 122 123 for(int i=0;i<m;++i){ 124 scanf("%I64d",&q[i].l); 125 q[i].id=i; 126 } 127 sort(q,q+m,cmp); 128 129 for(int i=0;i<m;++i){ 130 int ans,start=1; 131 if(!i) ans=1; 132 else ans=an[q[i-1].id]; 133 while(1){ 134 int j=start+ans-1; 135 for(;j<=n&&get_max(start,j)-get_min(start,j)<=q[i].l;++j); 136 if(ans<j-start) ans=j-start; 137 if(j==n+1) break; 138 ++start; 139 } 140 an[q[i].id]=ans; 141 } 142 for(int i=0;i<m;++i) printf("%d\n",an[i]); 143 } 144 return 0; 145 }