CF1129E Legendary Tree 构造

传送门


神树可还行

我们令(1)为树根,那么如果要询问(x)是否在(y)子树中,就令(S = {1} , T = {x} , u = y),询问一下就可以知道了。

那么考虑先构造出一个这样的序列(a_i):对于树上的每一个节点(u),它的父亲在这个序列上的位置在它的前面。

考虑增量构造。假如说我们已经构造出了(1)(i)的序列,现在要把(i+1)插入。有一种显然正确的构造方法:在序列上二分,找到一个最大的位置(p)满足(S = {1} , T = {a_1,a_2,...,a_p} , u = i+1)时询问答案为(0),将这个数放在(a_p)之后即可。

接下来我们可以找边了。对于每一个点,我们找它的所有儿子,而它的儿子一定在序列的后面的位置。于是在(a_i)上从右往左扫,用一个vector维护当前未找到父亲的点的集合(P)。对于点(i),先询问(S = {1} , T = P , u = a_i)时是否存在答案,如果不存在直接退出,否则二分出在(P)中最靠前的儿子(P_j),连上边((i,P_j)),然后再对于(P' = {P_{j+1},P_{j+2},...,P_{|P|}})做这样的操作就可以了。

复杂度:构造序列需要(nlogn)、每一个儿子被找到需要(nlogn)、每一个点失败的询问总共(n)次,加起来(2nlogn+n)可以通过本题。

#include<iostream>
#include<cstdio>
#include<vector>
//This code is written by Itst
using namespace std;

#define PII pair < int , int >
int N;
vector < PII > Edge;
vector < int > S , T , arr , son;

bool query(int u){
	cout << S.size() << endl;
	for(auto t : S) cout << t << ' ';
	cout << endl << T.size() << endl;
	for(auto t : T) cout << t << ' ';
	cout << endl << u << endl;
	int x; cin >> x; return x;
}

void answer(){
	cout << "ANSWER" << endl;
	for(auto t : Edge) cout << t.first << ' ' << t.second << endl;
}

int main(){
	ios::sync_with_stdio(0);
	cin >> N;
	S.push_back(1);	arr.push_back(2);
	for(int i = 3 ; i <= N ; ++i){
		int L = 0 , R = i - 2;
		while(L < R){
			int mid = (L + R + 1) >> 1;
			T.clear(); T.insert(T.begin() , arr.begin() , arr.begin() + mid);
			query(i) ? R = mid - 1 : L = mid;
		}
		arr.insert(arr.begin() + L , i);
	}
	son.push_back(*--arr.end());
	auto it = --arr.end();
	while(it-- != arr.begin()){
		auto t = son.begin();
		while(t != son.end()){
			T.clear(); T.insert(T.begin() , t , son.end());
			if(!query(*it)) break;
			int L = 0 , R = son.end() - t - 1;
			while(L < R){
				int mid = (L + R) >> 1;
				T.clear(); T.insert(T.begin() , t , t + mid + 1);
				query(*it) ? R = mid : L = mid + 1;
			}
			while(L){++t; --L;}
			auto t1 = t; Edge.push_back(PII(*it , *t)); son.erase(t1);
		}
		son.push_back(*it);
	}
	for(auto t : son) Edge.push_back(PII(t , 1));
	answer();
	return 0;
}
原文地址:https://www.cnblogs.com/Itst/p/10512584.html