萌新 MLE 25pts 求调
查看原帖
萌新 MLE 25pts 求调
638491
Illus1onary_Real1ty楼主2024/9/18 11:14

AC 第一个点,其余 MLE。

做法:考虑构建 Kruskal 重构树,每次查询倍增寻找深度最前的 valxval \le x 的祖先,查询子树第 kk 大的数,考虑可持久化权值线段树(主席树)。

自己算了一下所需空间大约在 63 mb 左右,应该不存在数组开大的情况。

代码中没有分配动态内存,也没有使用指针,不存在内存泄漏的情况,2 gb 的空间情况下爆栈也不可能。

这里是代码:

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

const int N = 1e5 + 10;
const int M = 5e5 + 10;
int n, m, q, h[N], tot = 0, t[N], cnt;
int ls[N << 1], rs[N << 1], val[N << 1];

struct Edge{
	int u, v, w;
	Edge(){}
	Edge(int u_, int v_, int w_){
		u = u_, v = v_, w = w_;
	}
	il bool operator < (const Edge& b) const{
		return w < b.w;
	}
}e[M];

struct Disjoint_Set{
	static const int MR = 1e5 + 10;
	int fa[MR];
	il void INIT(){
		for (int i = 1; i <= (n << 1); i++)
			fa[i] = i;
	}
	il int FIND(int x){
		return (fa[x] == x ? x : (fa[x] = FIND(fa[x])));
	}
	il void MERGE(int x, int y, int w){
		x = FIND(x), y = FIND(y);
		++cnt;
		fa[x] = fa[y] = cnt;
		ls[cnt] = x, rs[cnt]= y;
		val[cnt] = w;
	}
}ds;

int fa[N << 1][20], dfncnt = 0, dfn[N], rk[N];
int in[N << 1], out[N << 1];

il void EX_Kruskal(){
	ds.INIT();
	cnt = n;
	sort(e + 1, e + m + 1);
	for (int i = 1, u, v, w; i <= m; i++){
		u = ds.FIND(e[i].u);
		v = ds.FIND(e[i].v);
		w = e[i].w;
		if (u ^ v)
			ds.MERGE(u, v, w);
	}
}

il void DFS(int u, int fno){
	fa[u][0] = fno;
	for (int i = 1; i < 20; i++)
		fa[u][i] = fa[fa[u][i - 1]][i - 1];
	
	if (u <= n){
		++dfncnt;
		dfn[u] = in[u] = out[u] = dfncnt;
		rk[dfncnt] = u;
		return;
	}
	in[u] = dfncnt + 1;
	DFS(ls[u], u), DFS(rs[u], u);
	out[u] = dfncnt;
}

struct Segment_Tree{
	static const int MR = 1e5 + 10;
	int tot = 0, root[MR];
	int xds[MR << 5], ls[MR << 5], rs[MR << 5];
	il void Push_Up(int rt){
		xds[rt] = xds[ls[rt]] + xds[rs[rt]];
	}
	il void Update(int &rt1, int rt2, int l, int r, int x){
		rt1 = (rt1 ? rt1 : (++tot));
		xds[rt1] = xds[rt2] + 1;
		if (l == r)
			return;
		int md = (l + r) >> 1;
		if (x <= md)
			Update(ls[rt1], ls[rt2], l, md, x), rs[rt1] = rs[rt2];
		else	Update(rs[rt1], rs[rt2], md + 1, r, x), ls[rt1] = ls[rt2];
		Push_Up(rt1);
	}
	il int Query(int rt1, int rt2, int l, int r, int k){
		if (l == r)
			return t[l];
		int cnt = xds[rs[rt2]] - xds[rs[rt1]];
		//cout << rt1 << " " << rt2 << " " << l << " " << r << " " << cnt << endl;
		int md = (l + r) >> 1;
		return (k <= cnt ? Query(rs[rt1], rs[rt2], md + 1, r, k) :
						   Query(ls[rt1], ls[rt2], l, md, k - cnt));
	}
}sgt;

il void Solve(){
	int v, x, k;
	cin >> v >> x >> k;
	for (int i = 19; i >= 0; i--)
		if (fa[v][i] && val[fa[v][i]] <= x)
			v = fa[v][i];
	//cout << v << " " << in[v] << " " << out[v] << endl;
	if (out[v] - in[v] + 1 < k)
		cout << -1 << endl;
	else	cout << sgt.Query(sgt.root[in[v] - 1], sgt.root[out[v]], 1, tot, k) << endl;
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m >> q;
	for (int i = 1; i <= n; i++){
		cin >> h[i];
		t[++tot] = h[i];
	}
	sort(t + 1, t + tot + 1);
	tot = unique(t + 1, t + tot + 1) - t - 1;
	for (int i = 1; i <= n; i++)
		h[i] = lower_bound(t + 1, t + tot + 1, h[i]) - t;
	for (int i = 1, u, v, w; i <= m; i++){
		cin >> u >> v >> w;
		e[i] = Edge(u, v, w);
	}
	
	EX_Kruskal();
	DFS(cnt, 0);
	//for (int i = 1; i <= cnt; i++)
		//cout << ls[i] << " " << rs[i] << " " << val[i] << endl;
	for (int i = 1; i <= n; i++){
		sgt.Update(sgt.root[i], sgt.root[i - 1], 1, tot, h[rk[i]]);
		//cout << rk[i] << " " << h[rk[i]] << endl;
	}
	//cout << sgt.Query(sgt.root[1], sgt.root[8], 1, tot, 1) << endl;
	
	while (q--)
		Solve();
	
	return 0;
}
2024/9/18 11:14
加载中...