题意是说给出一棵树,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 }
时间: 2024-10-29 19:05:48