这样的思路对不对
查看原帖
这样的思路对不对
809729
SJZ2010楼主2024/6/27 08:32

我觉得这个题就是求 树上一个点集的 直径,所以我觉得似乎可以选择 离重心最远的一个点 开始点分树的暴力跳父亲。

但是只过 hack,求问这样做可不可行。不可行能不能给个小数据把代码 hack 了。

Code:

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

using LL = __int128;
using ll = long long;
using ldb = long double;
using vi = vector < int >;
#define ve vector < edge >
#define pb(x) emplace_back(x)
#define lowbit(x) ((x) & -(x))
#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 debug cerr << __FILE__ << ": " << __LINE__ << '\n';
#define qio() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
const int N = 1e5 + 5; // Adjust
const int LG = 19;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int read() {
	int res(0);
	char ch(getchar());
	while (ch < '0' || ch > '9')
		ch = getchar();
	while (ch >= '0' && ch <= '9') {
		res = res * 10 + (ch ^ '0');
		ch = getchar();
	}
	return res;
}

struct edge {
	int v, w;
};
struct vertex { // 这个东西放到优先队列里,用来求离重心最远的点
	int u, dep;
	inline bool operator < (const vertex& x) const {
		return dep < x.dep;
	}
	inline bool operator == (const vertex& x) const {
		return u == x.u && dep == x.dep;
	}
	inline void operator += (const vertex& x) const {
		// 只用于避免编译错误
	}
	inline bool operator <= (const vertex& x) const { 
		return *this < x | *this == x;
	}
};
template < class T >
struct deletable_heap { // 可删堆
#define DEL 1
#define USE 0
	priority_queue < T > Q[2];
	
	inline void push(T x) {
		Q[USE].push(x);
	}
	inline void remove(T x) {
		Q[DEL].push(x);
	}
	inline void pop() {
		Q[USE].pop();
	} 
	inline T top() {
		while (!Q[DEL].empty() && !Q[USE].empty() && Q[USE].top() <= Q[DEL].top()) {
			Q[USE].pop();
			Q[DEL].pop();
		}
		return Q[USE].top();
	}
	inline int size() {
		return Q[USE].size() - Q[DEL].size();
	}
	inline T exact_pop() {
		return Q[USE].top();
	}
	inline T sum2() { // top + sectop
		T ret = Q[USE].top(), tmp = ret;
		Q[USE].pop();
		ret += top();
		push(tmp);
		return ret;
	}
};

int n, dist[N];
ve G[N];
bool sit[N];

namespace LCA { // 计算点之间的距离
	int cnt(0), dfn[N], dep[N], rmq[LG][N];
	
	inline int get(int a, int b) {
		return dfn[a] < dfn[b] ? a : b;
	}
	void dfs(int u, int fa) {
		rmq[0][dfn[u] = ++cnt] = fa;
		for (edge e : G[u])
			if (e.v != fa) {
				dep[e.v] = dep[u] + e.w;
				dfs(e.v, u);
			}
	}
	void init() {
		dfs(1, 0);
		L(i, 1, __lg(n))
			L(j, 1, n + 1 - (1 << i))
				rmq[i][j] = get(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]);
	}
	inline int lca(int u, int v) {
		if (u == v)
			return v;
		if ((u = dfn[u]) > (v = dfn[v]))
			swap(u, v);
		int d = __lg(v - u++);
		return get(rmq[d][u], rmq[d][v - (1 << d) + 1]);
	}
	inline int dis(int u, int v) {
		int l = lca(u, v);
		return dep[u] + dep[v] - 2 * dep[l];
	}
} using LCA::dis;
namespace DCT {
	deletable_heap < int > A[N], B[N], C;
	int rt, sum, sz[N], f[N], rf[N];
	bool vis[N];
	
	void centroid(int u, int fa) {
		sz[u] = 1;
		f[u] = 0;
		for (edge e : G[u]) 
			if (e.v != fa && !vis[e.v]) {
				centroid(e.v, u);
				sz[u] += sz[e.v];
				f[u] = max(f[u], sz[e.v]);
			}
		f[u] = max(f[u], sum - sz[u]);
		if (f[u] < f[rt])
			rt = u;
	}
	void rebuild(int u, int fa) { // 重构
		vis[u] = 1;
		sz[u] = sum + 1;
		
		int v;
		for (edge e : G[u]) {
			v = e.v;
			if (v != fa && !vis[v]) {
				sum = sz[v];
				rt = 0;
				centroid(v, u);
				centroid(rt, 0);
				rf[rt] = u;
				rebuild(rt, u);
			}
		}
	}
	
	void init() { // 在询问及修改开始前对点进行初始化
		L(u, 1, n)
			for (int i = u; rf[i]; i = rf[i])
				A[i].push(dis(u, rf[i]));
		L(i, 1, n)
			B[rf[i]].push(A[i].top());
	}
	void off(int u) { // 关灯
		for (int i = u; rf[i]; i = rf[i]) {
		//	C.remove(B[rf[i]].sum2());
			B[rf[i]].remove(A[i].top());
			A[i].push(dis(u, rf[i]));
			B[rf[i]].push(A[i].top());
		//	C.push(B[rf[i]].sum2());
		}
	}
	void light(int u) { // 开灯
		for (int i = u; rf[i]; i = rf[i]) {
		//	C.remove(B[rf[i]].sum2());
			B[rf[i]].remove(A[i].top());
			A[i].remove(dis(u, rf[i]));
			B[rf[i]].push(A[i].top());
		//	C.push(B[rf[i]].sum2());
		}
	}
	int query(int u) { // 查询
		int res(0);
		for (int i = u; i; i = rf[i]) 
			if (B[i].size() > 2 || !sit[i])
				res = max(res, B[i].sum2());
		return res;
	}
}

int main() {
	qio();
	cin >> n;
	for (int i = 1, u, v; i < n; i++) {
		cin >> u >> v;
		G[u].push_back({v, 1});
		G[v].push_back({u, 1});
	}
	
	LCA::init();
	
	DCT::f[DCT::rt = 0] = inf, DCT::sum = n;
	DCT::centroid(1, 0);
	DCT::centroid(DCT::rt, 0);
	deletable_heap < vertex > q;
	L(i, 1, n)
		q.push({i, dis(i, dist[i] = DCT::rt)});
	DCT::rebuild(DCT::rt, 0);
	
	L(i, 1, n)
		DCT::A[i].push(0), DCT::B[i].push(0);
	DCT::init();
	
	char ch;
	int Q, u, sum = n; // sum 记录还关着的灯
	cin >> Q;
	while (Q--) {
		cin >> ch;
		if (ch == 'C') {
			cin >> u;
			if (sit[u]) { // sit[u] == 1: light
				DCT::off(u);
				q.push({u, dist[u]});
				sum++;
			} else {
				DCT::light(u);
				q.remove({u, dist[u]});
				sum--;
			}
			sit[u] ^= 1; // 改变状态
		} else {
			printf("%d\n", sum ? (sum == 1 ? 0 : DCT::query(q.top().u)) : -1);
		}
	}
	
	return 0;
}
2024/6/27 08:32
加载中...