求调,样例都过不了/dk
查看原帖
求调,样例都过不了/dk
809729
SJZ2010楼主2024/9/14 21:12

已经调 3h+ 了/ll

样例是 LibreOJ 的大样例。思路是线段树分治,每个节点维护凸包。

#include <bits/stdc++.h>
using namespace std;

using LL = __int128;
using ll = long long;
using ldb = long double;
using vi = vector < int >;
using pii = pair < int, int >;
using ull = unsigned long long;
#define pb push_back
#define ls(u) (u << 1)
#define rs(u) (u << 1 | 1)
#define ve vector < edge >
#define lowbit(x) ((x) & -(x))
#define sz(x) (int((x).size()))
#define all(a) (a).begin(), (a).end()
#define me(a, b) memset(a, b, sizeof(a))
#define L(i, j, k) for (int i = j; i <= int(k); i++)
#define R(i, j, k) for (int i = j; i >= int(k); i--)
#define qio() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
namespace io {
#define CF
#ifdef FILE
	char buf[1 << 21], *p1 = buf, *p2 = buf;
	#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
#else
	#ifndef CF
		#define getchar() getchar_unlocked()
	#endif
#endif
	int read() {
		int x = 0, f = 1; char ch = getchar();
		while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
		while (ch >= '0' && ch <= '9') {
			assert(10ll * x + (ch ^ '0') <= INT_MAX);
			x = x * 10 + (ch ^ '0'), ch = getchar();
		} return x * f;
	}
	template < class T = int > void read(T& x) {
		x = 0; int f = 1; char ch(getchar());
		while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
		while (ch >= '0' && ch <= '9') { x = x * 10 + (ch ^ '0'), ch = getchar(); } x *= f;
	}
} using io::read;

template < class T > ostream& operator << (ostream& out, vector < T > v) {
	out << '[';  if (!v.empty()) { L(i, 0, v.size() - 2) out << v[i] << ','; out << v[v.size() - 1]; } return out << ']';
}
// #define DEBUG
namespace Dbg {
	template < class T > void dbg(char *f, T t) { cerr << f << '=' << t << endl; }
	template < class T, class ...Ar > void dbg(char *f, T x, Ar... y) {
		while (*f != ',') { cerr << *f++; } cerr << '=' << x << ','; dbg(f + 1, y...);
	}
}
#ifdef DEBUG
	#define gdb(...) cerr << "gdb in line " << __LINE__ << ": ", Dbg::dbg((char*)#__VA_ARGS__,__VA_ARGS__)
	#define debug cerr << "debug: " << __LINE__ << '\n'
#else
	#define gdb(...) void()
	#define debug void()
#endif

/* ================================= */

const int N = 5e5 + 5; // Adjust
const int V = 1e8 + 5;
const int notExist = -2e6 - 1;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;

#define F first
#define S second

struct Planet {
	ll k, b;
	vector < pii > influence;

	void split(pii del) {
		auto ori = influence.back();
		influence.pop_back();
		influence.pb({ori.F, del.F - 1});
		influence.pb({del.S + 1, ori.S});
	}
} planet[N];
struct Input {
	int opt, id;
} input[N];
struct Query {
	int u, x0, id;
	void input(int i) {
		u = read(), x0 = read(), id = i;
	}
} query[N];

struct point {
	ll x, y;
};
struct segment_tree {
	struct Convex {
		vector < point > pset;
		int head;

		Convex() {
			head = 0;
		}
		int size() {
			return sz(pset) - head;
		}
		bool pop_back(point a, point b, point c) {
			return 1ll * (b.y - a.y) * (c.x - b.x) > 1ll * (b.x - a.x) * (c.y - b.y);
		}
		bool useless(point a, point b, ll slope) {
			return b.y - a.y < slope * (b.x - a.x);
		}

		void add_back(point add) {
			while (size() > 1 && pop_back(pset[sz(pset) - 2], pset.back(), add))
				pset.pop_back();
			pset.pb(add);
		}
		ll query(ll x0) {
			while (size() > 1 && useless(pset[head], pset[head + 1], x0 * 2))
				++head, gdb(size());
			if (size() == 0)
				return INF;
			auto [x, y] = pset[head];
			gdb(x, y);
			return -2 * x0 * x + y + x0 * x0;
		}
	} convex[N << 2];

#define ls(u) (u << 1)
#define rs(u) (u << 1 | 1)

	void modify(int s, int t, int ql, int qr, int u, point add) {
		if (ql <= s && t <= qr) {
			convex[u].add_back(add);
			return;
		}
		int mid = (s + t) >> 1;
		if (mid >= ql)
			modify(s, mid, ql, qr, ls(u), add);
		if (mid < qr) 
			modify(mid + 1, t, ql, qr, rs(u), add);
	}
	ll query(int s, int t, int k, int u, ll x0) {
		ll res = convex[u].query(x0);
		gdb(s, t, k, u, x0, res);
		if (s == t) {
			return res;
		}
		int mid = (s + t) >> 1;
		if (mid >= k)
			return min(res, query(s, mid, k, ls(u), x0));
		else
			return min(res, query(mid + 1, t, k, rs(u), x0));
	}
} sgt;

int n, m, dfn_l[N], dfn_r[N];
bool exist[N];
vi G[N];

int get_dfs_order(int u) {
	static int dfc = 0;
	dfn_l[u] = dfn_r[u] = ++dfc;
	
	for (int v : G[u])
		dfn_r[u] = max(dfn_r[u], get_dfs_order(v));

	return dfn_r[u];
}
void get_influence_range(int u) {
	if (input[u].opt == 0) {
		planet[input[u].id].influence.pb({dfn_l[u], dfn_r[u]});
	} else {
		planet[input[u].id].split({dfn_l[u], dfn_r[u]});
	}
	
	for (int v : G[u])
		get_influence_range(v);
}

int main() {
	n = read(), m = read(), read < ll >(planet[0].b);
	L(i, 1, n - 1) { 
		int opt = read(), fa = read(), id = read();
		G[fa].pb(i);
		if (opt == 0) {
			int x = read(); read(), read();
			ll c; read < ll >(c);
			planet[id] = {x, 1ll * x * x + c};
		}
		input[i] = {opt, id};
		exist[id] = 1;
	}
	L(i, 0, m - 1) {
		query[i].input(i);
	}

	L(i, 1, n - 1)
		if (!exist[i])
			planet[i].k = notExist;

	get_dfs_order(0), get_influence_range(0);
	sort(query, query + m, [](Query a, Query b) {
		return a.x0 < b.x0;
	});
	sort(planet, planet + n, [](Planet a, Planet b) {
		return a.k != b.k ? a.k < b.k : a.b < b.b;
	});

	L(i, 1, n - 1)
		if (planet[i].k == planet[i - 1].k)
			planet[i].k = notExist;
	
	L(i, 0, n - 1)
		if (planet[i].k != notExist) {
			for (pii add : planet[i].influence)
				if (add.F <= add.S) 
					sgt.modify(1, n, add.F, add.S, 1, {planet[i].k, planet[i].b});
		}

	vector < ll > ans(m);
	L(i, 0, m - 1) {
//		cerr << "calcing " << query[i].id << '\n';
		ans[query[i].id] = sgt.query(1, n, dfn_l[query[i].u], 1, query[i].x0);
	}

	for (ll i : ans)
		printf("%lld\n", i);

	return 0;
}

2024/9/14 21:12
加载中...