在树上建立主席树。。。然后如果a>=b,那么就只建边,初始值主席树上查最小值。否则在建一条边或者不建边。不建边的情况下,在主席树上找最小的限制解。。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 100005 #define maxm 200005 #define eps 1e-7 #define mod 1000000007 #define INF 0x3f3f3f3f #define PI (acos(-1.0)) #define lowbit(x) (x&(-x)) #define mp make_pair #define ls o<<1 #define rs o<<1 | 1 //#define lson o<<1, L, mid //#define rson o<<1 | 1, mid+1, R #define pii pair<int, int> #pragma comment(linker, "/STACK:16777216") //typedef long long LL; //typedef unsigned long long ULL; //typedef int LL; using namespace std; //LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;} //LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;} // head #define lson o->ch[0], L, mid #define rson o->ch[1], mid+1, R const int LL = 0; const int RR = 10000; struct Edge { int v, w; Edge *next; }*H[maxn], *edges, E[maxm]; struct node { int cnt, sum; node *ch[2]; }*h[maxn], *tail, pool[maxm << 4]; const int M = 20; int anc[maxn][M]; int dep[maxn]; int n, m; void addedges(int u, int v, int w) { edges->v = v; edges->w = w; edges->next = H[u]; H[u] = edges++; } node* newnode() { tail->cnt = tail->sum = 0; tail->ch[0] = tail->ch[1] = NULL; return tail++; } int to(int u, int d) { for(int i = M - 1; i >= 0; i--) if(dep[anc[u][i]] >= d) u = anc[u][i]; return u; } int lca(int u, int v) { if(dep[u] < dep[v]) swap(u, v); u = to(u, dep[v]); for(int i = M - 1; i >= 0; i--) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i]; return u == v ? u : anc[u][0]; } void init() { tail = pool; edges = E; memset(H, 0, sizeof H); } node* build(int L, int R) { if(L == R) return newnode(); int mid = (L + R) >> 1; node *o = newnode(); o->ch[0] = build(L, mid); o->ch[1] = build(mid+1, R); return o; } void pushup(node *o) { o->cnt = o->ch[0]->cnt + o->ch[1]->cnt; o->sum = o->ch[0]->sum + o->ch[1]->sum; } node* update(node* o, int L, int R, int v) { node *p = newnode(); *p = *o; if(L == R) { p->cnt++, p->sum += v; return p; } int mid = (L + R) >> 1; if(v <= mid) p->ch[0] = update(lson, v); else p->ch[1] = update(rson, v); pushup(p); return p; } void dfs(int u, int fa) { anc[u][0] = fa; for(Edge *e = H[u]; e; e = e->next) if(e->v != fa) { int v = e->v, w = e->w; h[v] = update(h[u], LL, RR, w); dep[v] = dep[u] + 1; dfs(v, u); } } int query_min(node *a, node *b, node *c, int L, int R) { if(L == R) return L; int lcnt = a->ch[0]->cnt + b->ch[0]->cnt - 2 * c->ch[0]->cnt; int mid = (L + R) >> 1; if(lcnt) return query_min(a->ch[0], b->ch[0], c->ch[0], L, mid); else return query_min(a->ch[1], b->ch[1], c->ch[1], mid+1, R); } int query(node *a, node *b, node *c, int L, int R, int cnt, int kk) { if(L == R) { int t = a->cnt + b->cnt - 2 * c->cnt; if(cnt > kk) return L-1; else return L + (kk - cnt) / (cnt + t); } int lcnt = a->ch[0]->cnt + b->ch[0]->cnt - 2 * c->ch[0]->cnt; int lsum = a->ch[0]->sum + b->ch[0]->sum - 2 * c->ch[0]->sum; int mid = (L + R) >> 1; int t = cnt * (mid - L + 1) + lcnt * mid - lsum; if(t <= kk) query(a->ch[1], b->ch[1], c->ch[1], mid+1, R, cnt + lcnt, kk - t); else return query(a->ch[0], b->ch[0], c->ch[0], L, mid, cnt, kk); } void work() { int u, v, w, kk, a, b; scanf("%d%d", &n, &m); for(int i = 1; i < n; i++) { scanf("%d%d%d", &u, &v, &w); addedges(u, v, w); addedges(v, u, w); } h[1] = build(LL, RR); dfs(1, 1); for(int i = 1; i < M; i++) for(int j = 1; j <= n; j++) anc[j][i] = anc[anc[j][i-1]][i-1]; while(m--) { scanf("%d%d%d%d%d", &u, &v, &kk, &a, &b); int c = lca(u, v); int ans = query_min(h[u], h[v], h[c], LL, RR); if(a <= b) { ans += kk / a; printf("%d\n", ans); } else { int t1 = ans; if(kk > a) t1 += 1 + (kk - a) / b; int t2 = query(h[u], h[v], h[c], LL, RR, 0, kk / b); if(t1 > t2) printf("%d\n", t1); else printf("%d\n", t2); } } } int main() { int _; scanf("%d", &_); for(int i = 1; i <= _; i++) { printf("Case #%d:\n", i); init(); work(); } return 0; }