HDU 4123 Bob’s Race(RMQ)

题意是说给出一棵树,N(10^5)个顶点,以及每条边的权值,现在需要选择连续的K个点(顶点编号连续),可以被选出来的条件是:

                         若d[i]代表顶点i到树上其他点的距离的最大值,使得区间[a, b]的d值的最大差值不大于Q,

                         也就是max(d[a], d[a + 1], ..., d[b]) - max(d[a], d[a + 1], ..., d[b]) <= Q

Q是给出的一个查询(共有m<=500个查询),求对应每一个查询的K的最大值

 

思路是首先预处理出每个点到其他点的最大距离, 这可以通过两遍dfs算出来,然后对于每一个查询Q,找出一个最大长度的区间,使得这个区间的最大最小值差<=Q,所以还需要RMQ预处理出每个区间的最大值与最小值(这里查询需要做到O(1)),然后扫描一遍数组便可以得到这个最大长度的区间。

 

  1 #pragma comment(linker, "/STACK:1677721600")
  2 #include <map>
  3 #include <set>
  4 #include <stack>
  5 #include <queue>
  6 #include <cmath>
  7 #include <ctime>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <cctype>
 11 #include <cstring>
 12 #include <cstdlib>
 13 #include <iostream>
 14 #include <algorithm>
 15 using namespace std;
 16 #define INF 0x3f3f3f3f
 17 #define inf (-((LL)1<<40))
 18 #define lson k<<1, L, (L + R)>>1
 19 #define rson k<<1|1,  ((L + R)>>1) + 1, R
 20 #define mem0(a) memset(a,0,sizeof(a))
 21 #define mem1(a) memset(a,-1,sizeof(a))
 22 #define mem(a, b) memset(a, b, sizeof(a))
 23 #define FIN freopen("in.txt", "r", stdin)
 24 #define FOUT freopen("out.txt", "w", stdout)
 25 #define rep(i, a, b) for(int i = a; i <= b; i ++)
 26 #define dec(i, a, b) for(int i = a; i >= b; i --)
 27 
 28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
 29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
 30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
 31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
 32 
 33 //typedef __int64 LL;
 34 typedef long long LL;
 35 const int MAXN = 50000 + 100;
 36 const int MAXM = 110000;
 37 const double eps = 1e-8;
 38 LL MOD = 1000000007;
 39 
 40 struct Node {
 41     int v, s;
 42     Node(int _v = 0, int _s = 0) {
 43         v = _v; s = _s;
 44     }
 45 };
 46 
 47 vector<Node>G[MAXN];
 48 int mx[MAXN], se[MAXN], d[MAXN], idx[MAXN];
 49 int ma[MAXN][20], mi[MAXN][20];
 50 int n, u, v, w;
 51 int m, Q;
 52 
 53 void init(int n) {
 54     rep (i, 0, n) G[i].clear();
 55     mem0(mx); mem0(se);
 56 }
 57 
 58 void dfs1(int u, int fa) {
 59     mx[u] = se[u] = 0;
 60     int sz = G[u].size();
 61     rep (i, 0, sz - 1) {
 62         int v = G[u][i].v;
 63         if(v == fa) continue;
 64         dfs1(v, u);
 65         int len = G[u][i].s + mx[v];
 66         if(len > mx[u]) se[u] = mx[u], mx[u] = len;
 67         else if(len > se[u]) se[u] = len;
 68     }
 69 }
 70 
 71 void dfs2(int u, int fa, int dis) {
 72     d[u] = max(dis, max(mx[u], se[u]));
 73     int sz = G[u].size();
 74     rep (i, 0, sz - 1) {
 75         int v = G[u][i].v, len = G[u][i].s;
 76         if(v == fa) continue;
 77         if(len + mx[v] == mx[u])
 78             dfs2(v, u, max(dis, se[u]) + len);
 79         else
 80             dfs2(v, u, max(dis, mx[u]) + len);
 81     }
 82 }
 83 
 84 void rmq_init(int n) {
 85     rep (i, 1, n) ma[i][0] = mi[i][0] = d[i];
 86     for(int j = 1; (1<<j) <= n; j ++) {
 87         for(int i = 1; i + (1<<j) - 1 <= n; i ++) {
 88             ma[i][j] = max(ma[i][j - 1], ma[i + (1 << (j - 1))][j - 1]);
 89             mi[i][j] = min(mi[i][j - 1], mi[i + (1 << (j - 1))][j - 1]);
 90         }
 91     }
 92     rep (len, 1, n) {
 93         idx[len] = 0;
 94         while((1 << (idx[len] + 1)) <= len) idx[len] ++;
 95     }
 96 }
 97 
 98 int rmq(int l, int r) {
 99     int k = idx[r - l + 1];
100     return max(ma[l][k], ma[r - (1 << k) + 1][k]) - min(mi[l][k], mi[r - (1 << k) + 1][k]);
101 }
102 
103 int main()
104 {
105 //    FIN;
106     while(~scanf("%d %d", &n, &m) && n) {
107         init(n);
108         rep (i, 1, n - 1) {
109             scanf("%d %d %d", &u, &v, &w);
110             G[u].push_back(Node(v, w));
111             G[v].push_back(Node(u, w));
112         }
113 
114         //计算每个点到叶子节点的最远距离
115         dfs1(1, -1);
116         dfs2(1, -1, 0);
117 
118         //计算答案
119         rmq_init(n);
120         while(m --) {
121             scanf("%d", &Q);
122             int l = 1, ans = 0;
123             rep (i, 1, n) {
124                 while(l < i && rmq(l, i) > Q) l ++;
125                 ans = max(ans, i - l + 1);
126             }
127             cout << ans << endl;
128         }
129     }
130     return 0;
131 }

 

posted @ 2015-07-20 11:48  再见~雨泉  阅读(173)  评论(0编辑  收藏  举报