BZOJ 4009: [HNOI2015]接水果 (整体二分+扫描线 树状数组)

版权声明:本人版权意识薄弱,请随意转载 https://blog.csdn.net/Ike940067893/article/details/88737811

整体二分+扫描线 树状数组
具体做法看这里a

CODE

#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
template<class T>inline void read(T &res) {
    char ch; int flg = 1; for(;!isdigit(ch=getchar());)if(ch=='-')flg=-flg;
    for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0'); res*=flg;
}
const int MAXN = 40005;
struct matrix {
	int x[2], y[2], val;
	matrix(){}
	matrix(int minx, int maxx, int miny, int maxy, int v) {
		x[0] = minx, x[1] = maxx;
		y[0] = miny, y[1] = maxy; val = v;
	}
}a[MAXN<<1], b[MAXN<<2];
struct Query { int x, y, k, id; }q[MAXN], tmp[MAXN];
int n, m, tot, Q, ans[MAXN], fir[MAXN], to[MAXN<<1], nxt[MAXN<<1], cnt;
int mylg2[MAXN], dep[MAXN], f[MAXN][16], in[MAXN], out[MAXN], val[MAXN], tmr;
inline void add(int u, int v) {
	to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt;
	to[++cnt] = u; nxt[cnt] = fir[v]; fir[v] = cnt;
}
void dfs(int u) {
	in[u] = ++tmr;
	dep[u] = dep[f[u][0]] + 1;
	for(int i = fir[u]; i; i = nxt[i])
		if(to[i] != f[u][0])
			f[to[i]][0] = u, dfs(to[i]);
	out[u] = tmr;
}
inline void pre() {
	mylg2[1] = 0;
	for(int j = 1; j < 16; ++j) {
		mylg2[1<<j] = j;
		for(int i = 1; i <= n; ++i)
			f[i][j] = f[f[i][j-1]][j-1];
	}
}
inline int find(int u, int v) {
	int tmp = dep[v] - dep[u] - 1;
	while(tmp)
		v = f[v][mylg2[tmp&-tmp]], tmp -= tmp&-tmp;
	return v;
}
inline bool cmp(const matrix &A, const matrix &B) { return A.y[0] < B.y[0]; }
inline bool cmpv(const matrix &A, const matrix &B) { return A.val < B.val; }
inline bool cmpQ(const Query &A, const Query &B) { return A.y < B.y; }
int T[MAXN];
inline void upd(int x, int val) {
	while(x <= n) T[x] += val, x += x&-x;
}
inline int qsum(int x) {
	int res = 0;
	while(x) res += T[x], x -= x&-x;
	return res;
}

inline void calc(int ql, int qr, int L, int R) {
	for(int i = ql; i <= qr; ++i) val[i] = 0;
	int l = 1, r = tot+1, mid;
	while(l < r) {
		mid = (l + r) >> 1;
		if(a[mid].val < L) l = mid+1;
		else r = mid;
	}
	if(l > tot) return;
	int cur = 0;
	for(int i = l; i <= tot && a[i].val <= R; ++i) {
		b[++cur] = matrix(a[i].x[0], a[i].x[1], a[i].y[0], 0, 1);
		b[++cur] = matrix(a[i].x[0], a[i].x[1], a[i].y[1]+1, 0, -1);
	}
	if(!cur) return;
	sort(b + 1, b + cur + 1, cmp);
	sort(q + ql, q + qr + 1, cmpQ);
	int j = 1;
	for(int i = ql; i <= qr; ++i) {
		while(j <= cur && b[j].y[0] <= q[i].y) {
			upd(b[j].x[0], b[j].val), upd(b[j].x[1]+1, -b[j].val);
			++j;
		}
		val[i] = qsum(q[i].x);
	}
	while(j <= cur) upd(b[j].x[0], b[j].val), upd(b[j].x[1]+1, -b[j].val), ++j;
}
void solve(int ql, int qr, int vl, int vr) {
	if(ql > qr) return;
	if(vl == vr) { for(int i = ql; i <= qr; ++i) ans[q[i].id] = vl; return; }
	int vmid = (vl + vr) >> 1;
	calc(ql, qr, vl, vmid);
	int st = ql, ed = qr;
	for(int i = ql; i <= qr; ++i)
		if(val[i] >= q[i].k) tmp[st++] = q[i];
		else q[i].k -= val[i], tmp[ed--] = q[i];
	for(int i = ql; i <= qr; ++i) q[i] = tmp[i];
	solve(ql, st-1, vl, vmid);
	solve(ed+1, qr, vmid+1, vr);
}
int main () {
	read(n), read(m), read(Q);
	for(int i = 1, x, y; i < n; ++i)
		read(x), read(y), add(x, y);
	dfs(1); pre();
	int u, v, w, c;
	while(m--) {
		read(u), read(v), read(c);
		if(in[u] > in[v]) swap(u, v);
		if(in[u] <= in[v] && out[v] <= out[u]) { //u is anc of v
			w = find(u, v);
			a[++tot] = matrix(1, in[w]-1, in[v], out[v], c);
			if(out[w] < n) a[++tot] = matrix(in[v], out[v], out[w]+1, n, c);
		}
		else a[++tot] = matrix(in[u], out[u], in[v], out[v], c);
	}
	sort(a + 1, a + tot + 1, cmpv);
	for(int i = 1; i <= Q; ++i) {
		read(q[i].x), read(q[i].y), read(q[i].k), q[i].id = i;
		q[i].x = in[q[i].x], q[i].y = in[q[i].y];
		if(q[i].x > q[i].y) swap(q[i].x, q[i].y);
	}
	solve(1, Q, 0, 1e9);
	for(int i = 1; i <= Q; ++i) printf("%d\n", ans[i]);
}

猜你喜欢

转载自blog.csdn.net/Ike940067893/article/details/88737811