hdu 5840 This world need more Zhu (sqrt+树剖)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <functional>
#include <bitset>
using namespace std;


#define eps 1e-10
#define N 200020
#define M 200020
#define mod 772002
#define G 3
#define inf 0x3f3f3f3f
#define LL long long
#define pii pair<int, int>
#define MP make_pair
#define fi first
#define se second
#define ls (i << 1)
#define rs (ls | 1)
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define ui unsigned int


char buf[32000000],*pt = buf,*o = buf;
int getint(){
    int f = 1,x = 0;
    while((*pt != '-') && (*pt < '0' || *pt > '9'))    pt ++;
    if(*pt == '-')    f = -1,pt ++;    else    x = *pt++ - 48;
    while(*pt >= '0' && *pt <= '9')    x = x * 10 + *pt ++ - 48;
    return x * f;
}
char getch(){
    char ch;
    while(*pt < 'A' || *pt > 'Z')    pt ++;
    ch=*pt;pt++;
    return ch;
}


int n, q, fst[N], nxt[M], vv[M], e;
int a[N];
int B;

void init() {
	memset(fst, -1, sizeof fst);
	e = 0;
}
void add(int u, int v) {
	vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
}
int fa[N], dep[N], sz[N], son[N];
int tp[N];
int st[N], ed[N], lab[N], dc;
int ans[N];
int pos[N], num[N];
int mx[N << 2];
int L[N], R[N];

struct node {
	int u, p, b, k, id;
	node() {}
	node(int u, int p, int b, int k, int id):
		u(u), p(p), b(b), k(k), id(id) {}
	bool operator < (const node &vt) const {
		if(k != vt.k) return k < vt.k;
		return b < vt.b;
	}

}p[2 * N];
int tot;

void dfs1(int u, int p, int d) {
	dep[u] = d;
	fa[u] = p;
	sz[u] = 1;
	son[u] = 0;
	
	int mx = 0;
	for(int i = fst[u]; ~i; i = nxt[i]) {
		int v = vv[i];
		if(v == p) continue;
		dfs1(v, u, d + 1);
		sz[u] += sz[v];
		if(sz[v] > mx) son[u] = v, mx = sz[v];
	}
}


void dfs2(int u, int anc) {
	tp[u] = anc;
	st[u] = ++dc;
	lab[dc] = u;
	if(son[u]) dfs2(son[u], anc);
	for(int i = fst[u]; ~i; i = nxt[i]) {
		int v = vv[i];
		if(v == fa[u] || v == son[u]) continue;
		dfs2(v, v);
	}
	ed[u] = dc;
}
int lca(int u, int v) {
	while(tp[u] != tp[v]) {
		if(dep[tp[u]] > dep[tp[v]]) swap(u, v);
		v = fa[tp[v]];
	}
	if(dep[u] > dep[v]) swap(u, v);
	return u;
}
int kfa(int u, int k) {
	while(1) {
		if(dep[u] - dep[tp[u]] < k) {
			if(tp[u] == 1) return 0;
			k -= dep[u] - dep[tp[u]] + 1;
			u = fa[tp[u]];
		}
		else {
			return lab[st[u]-k];
		}
	}
}
int bf_query(int u, int p, int k, int b) {
	int t = ((dep[u] - b) % k + k) % k;
	u = kfa(u, t);
	int ret = 0;
	while(u && dep[u] >= dep[p]) {
		ret = max(ret, a[u]);
		u = kfa(u, k);
	}
	return ret;
}

void build(int ll, int rr, int i) {
	if(ll == rr) {
		mx[i] = a[lab[pos[ll]]];
		return;
	}
	build(lson);
	build(rson);
	mx[i] = max(mx[ls], mx[rs]);
}
int query(int l, int r, int ll, int rr, int i) {
	if(ll == l && rr == r) return mx[i];
	if(r <= md) return query(l, r, lson);
	if(l > md) return query(l, r, rson);
	return max(query(l, md, lson), query(md + 1, r, rson));
}

int calc_query(node x) {
	int b = x.b;
	if(L[b] == -1) return 0;
	int u = x.u;
	int p = x.p;
	int ret = 0;
	while(tp[u] != tp[p]) {
		int l = st[tp[u]], r = st[u];
		l = lower_bound(pos + L[b], pos + R[b] + 1, l) - pos;
		r = upper_bound(pos + L[b], pos + R[b] + 1, r) - pos - 1;
		if(l <= r) ret = max(ret, query(l, r, 1, n, 1));
		u = fa[tp[u]];
	}
	int l = st[p], r = st[u];
	l = lower_bound(pos + L[b], pos + R[b] + 1, l) - pos;
	r = upper_bound(pos + L[b], pos + R[b] + 1, r) - pos - 1;
	if(l <= r) ret = max(ret, query(l, r, 1, n, 1));
	return ret;
}


int main() {
	int cas, kk = 0;
	scanf("%d", &cas);
	while(cas--) {
		scanf("%d%d", &n, &q);
		for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
		B = sqrt(n + 0.5);
		init();
		for(int i = 1; i < n; ++i) {
			int u, v;
			scanf("%d%d", &u, &v);
			add(u, v);
			add(v, u);
		}
		dc = 0;
		dfs1(1, 0, 0);
		dfs2(1, 1);

		tot = 0;
		for(int i = 1; i <= q; ++i) {
			ans[i] = 0;
			int u, v, k;
			scanf("%d%d%d", &u, &v, &k);
			int fa = lca(u, v);
			int a = (dep[u] + 1) % k;
			int b = ((2 * dep[fa] - dep[u] - 1) % k + k) % k;
			if(k > B) {
				ans[i] = max(ans[i], bf_query(u, fa, k, a));
				ans[i] = max(ans[i], bf_query(v, fa, k, b));
			}
			else {
				p[++tot] = node(u, fa, a, k, i);
				p[++tot] = node(v, fa, b, k, i);
			}
		}
		sort(p + 1, p + tot + 1);
		for(int i = 1, j; i <= tot; i = j + 1) {
			j = i;
			while(j + 1 <= tot && p[i].k == p[j+1].k) ++j;
			int k = p[i].k;
			for(int u = 0; u < k; ++u) num[u] = 0, L[u] = R[u] = -1;
			for(int u = 1; u <= n; ++u) num[dep[lab[u]]%k]++;
			for(int u = 1; u < k; ++u) num[u] += num[u-1];
			for(int u = n; u >= 1; --u) pos[num[dep[lab[u]]%k]--] = u;
			for(int u = 1, v; u <= n; u = v + 1) {
				v = u;
				while(v + 1 <= n && dep[lab[pos[u]]] % k == dep[lab[pos[v+1]]] % k) ++v;
				L[dep[lab[pos[u]]]%k] = u;
				R[dep[lab[pos[u]]]%k] = v;
			}
			build(1, n, 1);
			
			for(int u = i; u <= j; ++u) {
				ans[p[u].id] = max(ans[p[u].id], calc_query(p[u]));
			}
		}
		printf("Case #%d:\n", ++kk);
		for(int i = 1; i <= q; ++i) {
			printf("%d\n", ans[i]);
		}
	}
	return 0;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值