题解 城市绿化

传送门

考场上胡了一个做法,证了一下是 \(O(n\log n)\) 的还挺开心的
结果考完才发现这玩意是 \(O(n^2)\)

于是来自 @401rk8 的吊打标算做法:感谢来自 @Yubai 的复杂度证明
先说做法:
首先树是以 1 为根的,那么可以用 n 次询问得到每个点 dep
然后按 dep 分层处理,假设我们已经得到 dep-1 这一层的形态,尝试得到 dep 这一层的形态
那么从 dep-1 这一层 rand 一个点,分别计算 dep-1 这层和 dep 这层所有点到这一个点的距离
那么 dis 等于 1 的就是它的子节点了
剩下会有一些点的 dis 相等无法确定,那么递归那个集合就好了
然后(粗略)证一下复杂度(备份一份 Yubai 的证明
(我并没有证只是在抄写 Yubai 的部分证明以方便以后弄不懂了回来看
先考虑完全二叉树的情况
设这一层的点数为 \(2^n\),那么应该有 \(T(n)=2^n+\sum\limits_{i=1}^{n-1}T(i)\)
解出来是 \(n\log n\) 级别的,这里 \(n\) 是点数
于是考虑不是完全二叉树的情况,需要将这一层切成若干块

\[T(n)=O(n)+T(i)T(n-i) \]

然后因为点是 rand 出来的,所以

\[T(n)=O(n)+\frac{1}{n}\sum\limits_{i=1}^nT(i)T(n-i)=O(n\log n) \]

于是这里总点数为 n
所以总复杂度为每层复杂度之和
令每层点数为 \(cnt_i\)

\[\sum T(cnt_i) < n\log n \]

点击查看代码
#include <bits/stdc++.h>
#include "green.h"
using namespace std;
#define N 100010
#define ll long long
#define fir first
#define sec second
#define pb push_back

int fa[N], dep[N];
vector<int> s1, s2, buc[N];

int visit(int, int);

void solve(vector<int> s1, vector<int> s2) {
	if (!s1.size() || !s2.size()) return ;
	if (s1.size()==1) {
		for (auto it:s2) fa[it]=s1[0];
		return ;
	}
	swap(s1[0], s1[rand()%s1.size()]);
	vector<pair<int, int>> t1, t2;
	vector<int> k1, k2;
	for (auto it:s1) t1.pb({s1[0]==it?0:visit(s1[0], it), it});
	for (auto it:s2) t2.pb({visit(s1[0], it), it});
	sort(t1.begin(), t1.end()); sort(t2.begin(), t2.end());
	int pos1=0, pos2=0;
	while (pos2<t2.size() && t2[pos2].fir==t1[pos1].fir+1) fa[t2[pos2++].sec]=t1[pos1].sec;
	++pos1;
	while (pos1<t1.size()) {
		k1.clear(); k2.clear();
		int tem=t1[pos1].fir;
		while (pos1<t1.size() && t1[pos1].fir==tem) k1.pb(t1[pos1++].sec);
		while (pos2<t2.size() && t2[pos2].fir==tem+1) k2.pb(t2[pos2++].sec);
		solve(k1, k2);
	}
}

void findtree(int n, int m, int* p) {
	random_device seed;
	mt19937 rand(seed());

	buc[0].pb(1);
	for (int i=2; i<=n; ++i) buc[dep[i]=visit(1, i)].pb(i);
	for (int i=1; i<=n; ++i) solve(buc[i-1], buc[i]);
	for (int i=2; i<=n; ++i) p[i]=fa[i];
	// cout<<"p: "; for (int i=1; i<=n; ++i) cout<<p[i]<<' '; cout<<endl;
}
posted @ 2022-01-21 21:01  Administrator-09  阅读(0)  评论(0编辑  收藏  举报