↓ Skip to main content
  1. Posts/

hdu 4123 Bob’s Race (树的直径+尺取+rmq)(珍爱生命,远离log)

·888 words·2 mins
Note: This article is available in Chinese only. 本文暂无英文版本。 View original

hdu 4123 题目链接

题意:一棵树,定义 d[i] 为点 i 到树上某点的最大距离。给出若干查询,每个查询一个 x,问最多能有多少点满足这些点中,最大的 d 与最小的 d 的差小于等于 x。要求这些点的编号必须是连续的。

思路:可以三遍 bfs 处理出所有点的 d…

由于不能排序,所以就是尺取+rmq….

然而神 Tm TLE…

这复杂度还 TLE…

结果最后发现是 log 运算的常数太大被卡。

所以做法是先预处理一下,嗯。

珍爱生命,远离log!
#

珍爱生命,远离log!
#

珍爱生命,远离log!
#

代码实现
  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年07月17日 星期日 19时37分55秒
  4File Name :code/hdu/4123.cpp
  5************************************************ */
  6#include <cstdio>
  7#include <cstring>
  8#include <iostream>
  9#include <algorithm>
 10#include <vector>
 11#include <queue>
 12#include <set>
 13#include <map>
 14#include <cmath>
 15#include <string>
 16#include <cstdlib>
 17#include <ctime>
 18#define fst first
 19#define sec second
 20#define lson l,m,rt<<1
 21#define rson m+1,r,rt<<1|1
 22#define ms(a,x) memset(a,x,sizeof(a))
 23typedef long long LL;
 24#define pi pair < int ,int >
 25#define MP make_pair
 26#define log2 0.693147
 27using namespace std;
 28const double eps = 1E-8;
 29const int dx4[4]={1,0,0,-1};
 30const int dy4[4]={0,-1,1,0};
 31const int inf = 0x3f3f3f3f;
 32const int N=1E5+7; //双向边。。。
 33int n,Q;
 34int head[N];
 35int d[5][N];
 36bool vis[N];
 37int ans;
 38int cnt;
 39int dp[N][30],dp2[N][30];
 40int beg,lst;
 41int LOG[N+10];
 42struct Edge
 43{
 44    int v;
 45    int w;
 46    int nxt;
 47}edge[N];
 48void addedge( int u,int v,int w)
 49{
 50    edge[cnt].v = v;
 51    edge[cnt].w = w;
 52    edge[cnt].nxt = head[u];
 53    head[u] = cnt;
 54    cnt++;
 55}
 56void rmq_init()
 57{
 58    for ( int i = 1 ; i <= n ; i++)
 59	dp[i][0] = dp2[i][0] = d[0][i];
 60    for ( int j = 1 ;  (1<<j)<=n; j++)
 61	for ( int i = 1 ; i + (1<<j) -1 <= n ; i++)
 62	{
 63	    dp[i][j] = max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
 64	    dp2[i][j] = min(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]);
 65	}
 66}
 67int rmq( int l,int r)
 68{
 69    if (l>r) return 0;
 70int k = log(double (r-l+1)/log2);
 71//int k = LOG[r-l+1];
 72//int k = 0;
 73//while (1<<(k+1)<=r-l+1) k++;
 74    int mx = max(dp[l][k],dp[r-(1<<k)+1][k]);
 75    int mn = min(dp2[l][k],dp2[r-(1<<k)+1][k]);
 76    return mx - mn;
 77}
 78void init()
 79{
 80    ms(head,-1);
 81    cnt = 0;
 82}
 83void bfs( int s,int k)
 84{
 85    ms(d[k],0x3f);
 86    ms(vis,false);
 87    queue<int>q;
 88    q.push(s);
 89    vis[s] = true;
 90    d[0][s]  = 0;
 91    while (!q.empty())
 92    {
 93	int u = q.front();
 94	q.pop();
 95	for ( int i = head[u] ; i !=-1 ; i = edge[i].nxt)
 96	{
 97	    int v = edge[i].v;
 98	    int w = edge[i].w;
 99	    if (vis[v]) continue;
100	    vis[v] = true;
101	    d[k][v] = d[k][u] + w;
102	    q.push(v);
103	}
104    }
105}
106void ruler(int k)
107{
108    int head = 1;
109    int tail = 1;
110    ans = 0 ;
111//    for ( int i = 1 ; i <= n ; i++) cout<<"d[0][i]:"<<d[0][i]<<endl;
112//   cout<<"k:"<<k<<endl;
113    while (tail<=n)
114    {
115	int cur = rmq(head,tail);
116//	cout<<"head:"<<head<<" tail:"<<tail<<" cur:"<<cur<<endl;
117	while (head<tail&&rmq(head,tail)>k) head++;
118	cur = rmq(head,tail);
119	if (cur<=k) ans = max(ans,tail-head);
120	tail++;
121    }
122    ans++;
123}
124void ruler2 ( int k)
125{
126    ans = 0 ;
127    int id = 1;
128    for ( int i = 1 ;i <= n ; i++)
129    {
130	while (id<=i&&rmq(id,i)>k) id++;
131	ans =max(ans,i-id+1);
132    }
133}
134int main()
135{
136	#ifndef  ONLINE_JUDGE
137	freopen("code/in.txt","r",stdin);
138  #endif
139	LOG[0] = -1;
140	for ( int i = 1 ; i < 2* N ; i++) LOG[i] =LOG[i>>1]+1;
141	while (scanf("%d%d",&n,&Q),n||Q)
142	{
143	  //  cout<<log(2.0)<<endl;
144	    init();
145	    for ( int i = 1 ; i <= n-1 ; i++)
146	    {
147		int u,v,w;
148		scanf("%d%d%d",&u,&v,&w);
149		addedge(u,v,w);
150		addedge(v,u,w);
151	    }
152	    bfs(1,0);
153	    int far = 0 ;
154	    for ( int i = 1 ; i <= n ; i++)
155		if (d[0][i]>far)
156		{
157		    far = d[0][i];
158		    lst  = i ;
159		}
160	    far = 0 ;
161	    bfs(lst,1);
162	    for ( int i = 1 ;i  <= n ; i++)
163		if (d[1][i]>far)
164		{
165		    far = d[1][i];
166		    beg = i ;
167		}
168	    bfs(beg,2);
169	    for ( int i = 1 ; i <= n ; i++)
170		d[0][i] = max(d[1][i],d[2][i]);
171	     rmq_init();
172	    while (Q--)
173	    {
174		int x;
175		scanf("%d",&x);
176		ruler(x);
177		printf("%d\n",ans);
178	    }
179	}
180  #ifndef ONLINE_JUDGE
181  fclose(stdin);
182  #endif
183    return 0;
184}

Related

hdu 3530 Subsequence (尺取+rmq)

·425 words·1 min
hdu 3530题目链接 题意:给出n个数,m,k,问最大的j-i+1,使得【i,j】间的最大值与最小值的差属于[m,k] 思路:rmq+尺取。 2A. 代码实现 1/* *********************************************** 2Author :111qqz 3Created Time :2016年05月19日 星期四 16时52分03秒 4File Name :code/hdu/3530.cpp 5************************************************ */ 6 7#include <cstdio> 8#include <cstring> 9#include <iostream> 10#include <algorithm> 11#include <vector> 12#include <queue> 13#include <set> 14#include <map> 15#include <string> 16#include <cmath> 17#include <cstdlib> 18#include <ctime> 19#define fst first 20#define sec second 21#define lson l,m,rt<<1 22#define rson m+1,r,rt<<1|1 23#define ms(a,x) memset(a,x,sizeof(a)) 24typedef long long LL; 25#define pi pair < int ,int > 26#define MP make_pair 27 28using namespace std; 29const double eps = 1E-8; 30const int dx4[4]={1,0,0,-1}; 31const int dy4[4]={0,-1,1,0}; 32const int inf = 0x3f3f3f3f; 33const int N=1E5+7; 34int n; 35int a[N]; 36int dp[N][20],dp2[N][20]; 37int m,k; 38 39void rmq_init() 40{ 41 for ( int i = 1 ; i <= n ; i ++) 42 dp[i][0] = dp2[i][0] = a[i]; 43 44 for ( int j = 1 ; (1<<j) <= n ; j++) 45 for ( int i = 1 ; i + (1<<j) -1 <= n ; i++) 46 { 47 dp[i][j] = max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); 48 dp2[i][j]=min(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]); 49 } 50} 51 52int rmq( int l,int r) 53{ 54 int k = 0 ; 55 while (1<<(k+1)<=r-l+1) k++; 56 int mx = max(dp[l][k],dp[r-(1<<k)+1][k]); 57 int mn = min(dp2[l][k],dp2[r-(1<<k)+1][k]); 58 59 return mx-mn; 60} 61 62int ruler() 63{ 64 int head = 1; 65 int tail = 1; 66 int res = -1 ; 67 while (tail<=n) 68 { 69 int cur = rmq(head,tail); 70 while (head<tail&&rmq(head,tail)>k) head++; 71 while (tail<n&&rmq(head,tail)<m) tail++; 72 //if (tail>n) break; 73 cur = rmq(head,tail); 74 if (cur>=m&&cur<=k) 75 { 76 res = max(res,tail-head); 77 } 78// cout<<"head:"<<head<<" tail:"<<tail<<" cur:"<<cur<<" res:"<<res<<endl; 79 tail++; 80 81 } 82 return res+1; 83} 84int main() 85{ 86 #ifndef ONLINE_JUDGE 87 freopen("code/in.txt","r",stdin); 88 #endif 89 90 while (scanf("%d %d %d",&n,&m,&k)!=EOF) 91 { 92 ms(dp,0); 93 for ( int i = 1 ; i <= n ; i++) scanf("%d",&a[i]); 94 if (m>k) 95 { 96 puts("0"); 97 continue; 98 } 99 rmq_init(); 100 printf("%d\n",ruler()); 101 } 102 103 104 105 #ifndef ONLINE_JUDGE 106 fclose(stdin); 107 #endif 108 return 0; 109}

POJ 1849 Two (树的直径)

·786 words·2 mins
题目链接 题意:一棵树。。然后初始两个推雪机在点s,问如何选择路径使得处理完所有边上的积雪所耗费的汽油最少(走过一条有雪的边和一条没雪的边耗费的汽油一样) 思路:很容易想到,我们应该尽可能不走已经被清理过雪了的边,因为这样很浪费。。。这样不难想到应该是和树的直径有关。但是初始的位置是给定的。。。怎么办?突然发现由于是给了两个推雪机。。所以其实相当于。。。只有一个推雪机&我们可以从任意位置开始推雪。。。第二个问题是。。。对于不在直径上的边。。我们怎么算cost?解决办法是读边的时候进行记录。。。然后求直径的时候记录路径。。。对于一条边。。。只要有一个点不在直径上。。。那么这条边的代价就是2倍。。。

hdu 4607 Park Visit (树的直径,推公式)

·748 words·2 mins
hdu4607题目链接 题意:给出一棵树。。。边权都为1. m个查询。。每个查询给一个k,表示只访问k个点。。。问每次的最小路径和是多少。。。 思路:我们发现。。会使路径和变大的一个不利因素是折返。。也就是访问某景点后。。必须要回去才能继续前进。。这样的距离是2倍。。那为了使得路径和尽可能小。。我们就尽量不要访问这样的点。。。而不是这样的点一定在直径上。。。以及我们还发现。。。不在直径上的点。。 。。不管深度如何(深度的意思是说,与和该点最近的直径上的点的距离),距离的贡献是一样的。。都是2倍。。所以我们可以推出一个公式。。。如果树的直径是d,那么k<=d+1的时候,答案为k-1,否则答案为d+(k-d-1)*2。。。

poj 3310 Caterpillar (树的直径+并查集判环+dfs判断连通性)

poj 3310 题目链接 题意:给出一个无向图,问是否满足:连通,并且无环,并且能找到一条路径,图中所有的顶点要么在这条路径上,要么与这条路径上的顶点相邻。 思路:一个一个来。连通的话任意起点开始跑一遍 dfs?开一个 bool 数组标记走过的点,最后扫一遍,看是否有点没走过。

hdu 4514 湫湫系列故事——设计风景线 (无向图并查集判环+非联通图的最长路径)

·897 words·2 mins
hdu 4514 题意:给出一个无向图,问是否有环,有的话输出 YES。如果没有环的话,输出最长路径。 思路:无向图判环用并查集就好。关于最长路径这里,一开始以为就是树的直径。 但是需要注意的是,题目并没有保证图一定是联通的,所以 gg 了。