您的位置:首页 > 其它

HDU 4123 Bob’s Race(树形DP + 单调队列)

2015-08-08 16:43 363 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4123

题意:给一颗N个点的树,对于每个点i先要找出离它最远的点的距离,设该距离为dis[i],再给M个询问,寻找dis数组中最大值与最小值之差不超过Q的最长连续区间的长度

思路:先找出树的直径的两端点,树上任意点一定是到这两端点中的某一点的距离最远,这样就能处理出dis数组,然后再用两个单调队列去维护区间最大最小值,用类似尺取法的思路去更新答案

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <climits>
#include <functional>
#include <deque>
#include <ctime>

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#pragma comment(linker, "/STACK:102400000,102400000")

using namespace std;

typedef long long ll;

const int maxn = 50010;

int cnt, head[maxn];
int dis1[maxn], dis2[maxn], dis[maxn];
int n, m;

struct edge
{
int to, w, next;
} e[maxn << 1];

void init()
{
cnt = 0;
memset(head, -1, sizeof(head));
}

void addedge(int u, int v, int w)
{
e[cnt].to = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt++;
}

void dfs1(int u)
{
for (int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].to;

if (dis1[v] == -1)
{
dis1[v] = dis1[u] + e[i].w;
dfs1(v);
}
}
}

void dfs2(int u)
{
for (int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].to;

if (dis2[v] == -1)
{
dis2[v] = dis2[u] + e[i].w;
dfs2(v);
}
}
}

void tree_Dia()
{
int u, v, len;

memset(dis1, -1, sizeof(dis1));
dis1[1] = 0;
dfs1(1);
len = 0;
for (int i = 1; i <= n; i++)
{
if (dis1[i] > len)
{
len = dis1[i];
u = i;
}
}

memset(dis1, -1, sizeof(dis1));
dis1[u] = 0;
dfs1(u);
len = 0;
for (int i = 1; i <= n; i++)
{
if (dis1[i] > len)
{
len = dis1[i];
v = i;
}
}

memset(dis2, -1, sizeof(dis2));
dis2[v] = 0;
dfs2(v);

for (int i = 1; i <= n; i++)
dis[i] = max(dis1[i], dis2[i]);
}

int qmi[maxn], qma[maxn];

void solve(int q)
{
int f1 = 0, r1 = 0;
int f2 = 0, r2 = 0;

int ans = 0, l = 0;
for (int i = 1; i <= n; i++)
{
while (f1 < r1 && dis[qmi[r1 - 1]] >= dis[i]) r1--;
qmi[r1++] = i;

while (f2 < r2 && dis[qma[r2 - 1]] <= dis[i]) r2--;
qma[r2++] = i;

while (dis[qma[f2]] - dis[qmi[f1]] > q)
{
l++;
if (qmi[f1] <= l) f1++;
if (qma[f2] <= l) f2++;
}
ans = max(ans, i - l);
}
printf("%d\n", ans);
}

int main()
{
while (~scanf("%d%d", &n, &m) && (n + m))
{
init();
for (int i = 0; i < n - 1; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
addedge(v, u, w);
}

tree_Dia();
while (m--)
{
int q;
scanf("%d", &q);
solve(q);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: