首页 > 其他分享 >题解 P2276 [HNOI2002]农场的果树

题解 P2276 [HNOI2002]农场的果树

时间:2023-07-17 21:22:52浏览次数:45  
标签:sz return rs int 题解 HNOI2002 rz P2276 lz

首先可以观察出一颗 \(n\) 个节点的二叉树,当其字典序最小的时候,其形态为一条向右偏的链,当其字典序最大的时候,是一条向左偏的链。

由于每一种编码对应唯一的一颗二叉树,我们可以先建树。

然后考虑树上分治,尝试以下三种方式:

  1. 变大右子树的字典序

  2. 变大左子树的字典序,并将右子树变成一条链

  3. 将左子树的大小 \(+1\) ,右子树的大小 \(-1\) ,然后都转化成一条向右偏的链

递归边界为 \(sz[u]==2\)

注意:当 \(n\) 个节点无解时,输出 \(n+1\) 个节点的树的最小字典序,即一条右偏链

顺便请求加强一下数据

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 5000 + 5;
int a[N], ls[N], rs[N], sz[N], n = 0, tot = 0, w = 1;
vector<int> v[N]; //v[u]表示u这棵子树的字典序
void dfsp(int siz) { //建树
	sz[++n] = siz;
	if (siz == 1) return;
	int lz = a[w + 1], rz = siz - a[w + 1] - 1, u = n;
	if (lz >= 1) {ls[u] = n + 1; if (lz > 1) ++w; dfsp(lz);}
	if (rz >= 1) {rs[u] = n + 1; if (rz > 1) ++w; dfsp(rz);}
}
bool dfs(int u) { //修改
	if (sz[u] == 2) {
		if (rs[u] == 0) return false; //只有左儿子,没法变大
		v[u].push_back(1);
		return true;
	}
	int lz = sz[ls[u]], rz = sz[rs[u]], num = 0;
	if (rz >= 2 && dfs(rs[u])) return true; //左
	if (lz >= 2 && dfs(ls[u])) { //右
		for (int i = 1; i < sz[rs[u]]; ++i) v[rs[u]].push_back(0);
		return true;
	} if (rz) { //左子树+1,右子树-1
		v[u].push_back(lz + 1);
		if (rz == 1) num = sz[u] - 2; //注意特判一下右子树大小为1的情况
		else num = sz[u] - 3;
		for (int i = 1; i <= num; ++i) v[u].push_back(0);
		return true;
	}
	return false;
}
void print(int u) {
	if (!u || sz[u] == 1) return;
	if (v[u].size()) {
		for (int i = 0; i < v[u].size(); ++i) cout << v[u][i] << " ";
		return;
	}
	cout << sz[ls[u]] << " ";
	print(ls[u]); print(rs[u]);
}
int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	while (cin >> a[++tot]){}
	--tot; dfsp(a[1]);
	if (dfs(1)) {cout << n << " "; print(1);}
	else { //n个节点无法满足要求,输出n+1个节点的最小字典序
		cout << n + 1 << " ";
		for (int i = 1; i <= n; ++i) cout << 0 << " ";
		cout << endl;
	}
	return 0;
}

标签:sz,return,rs,int,题解,HNOI2002,rz,P2276,lz
From: https://www.cnblogs.com/HQJ2007/p/17561248.html

相关文章

  • 题解 P7640 [BalticOI 2006 Day 2] CITY PLANNING
    首先我们定义“圈”为与原点距离相等的点集。...3.....323...32123.3210123.32123...323.....3...暴力:把圈放到堆里,然后每次取出代价最小的一圈,修改当前圈的楼层,向外圈拓展。正解:考虑二分。如果是二分最终答案,我们会发现......
  • 题解 P7250 [BalticOI 2012 Day1] 山峰
    通过观察,可以发现此题和最小生成树十分相似(两个地点之间途经的最小值最大)。于是可以考虑这么做:通过bfs将每一个块预处理出来,并记录其编号、高度、类型(是否为高地)以及边缘的点。将每一个块按高度从大到小排序。依次枚举每个块:对于当前要处理的块,枚举其边界的所有点,......
  • 题解 AT3726 [ARC087B] FT Robot
    首先可以观察到一个非常重要的性质:对于一次前进的操作,如果前面有奇数次转向,则走上下,否则走左右。(当然如果一开始就前进就只能走右)于是我们可以将其拆成许多的“块”,并分成两类,即前进方向为左右还是上下。然后对于两个维度分别dp。\(f_{i},_{j}=f_{i-1},_{j-val}\|\f_{i-......
  • Charles抓取https请求及常见问题解决
    一、背景APP测试的时候,通常都需要通过抓包工具抓取各类请求,查看接口的入参、返回值等,用于分析定位问题。常用的抓包工具有fiddler、charles等,抓取http的请求比较简单,https的请求稍显复杂。由于更喜欢charles的页面风格,本篇文章主要介绍以下两点:1、Charles如何抓取电脑端和手机端的......
  • CF1808C Unlucky Numbers 题解
    可以证明答案是\(l\)或\(r\)的一段前缀,拼上后面全部相同的一段字符\(d\),证明方式类似数位dp。能够自由填的数字一定是相等的,这样不会影响幸运值。前面那些不能自由填写的,就是\(l\)或\(r\)的一段前缀。假如不是\(l\)或\(r\)的一段前缀,必然填写相等的更好,而这种情况已......
  • P7809 [JRKSJ R2] 01 序列 题解
    前言传送门blog思路Problem1问题一问的是最长不下降子序列的长度,在一个$01$串中的最长不下降子序列,总共有三种$000\dots$,$000\dots111\dots$和$111111\dots$。可以把找到以上三种最长不下降子序列问题变为:$$\max^r_{i=l}(\sum_{j=l}^i[a_j=0])+(\sum_{j=i+1}^......
  • P7333 [JRKSJ R1] JFCA 题解
    前言传送门blog思路首先看数据范围$10^5$,$O(n\log_2n)$可以过,自然想到二分。二分具有单调性,那么如何确保整个$a$序列按顺序排列呢?我们可以使用st表维护区间最大值,如果在这个距离中已经有了$a_i\geb_j$那么最大值一定指向的是新加入进来的那个值,否则在之前二分就......
  • P8708 [蓝桥杯 2020 省 A1] 整数小拼接 题解
    前言传送门blog思路这种选出两个数拼接在一起的题,一看就可以使用two-point,我们使用$l$和$r$分别从最大的和最小的开始搜索,进行两次。以$l$为头,$r$为尾。以$r$为头,$l$为尾。如何比较大小呢?我们可以先去做宇宙总统这道题。首先排序的$cmp$:boolcmp(strin......
  • UVA10791 最小公倍数的最小和 Minimum Sum LCM 题解
    前言长沙市一中8机房0714模拟测1。传送门blog思路本题思路,首先我们先看$\operatorname{lcm}$,明显要使得这些数的$\operatorname{lcm}=n$那么我们就需要所有的数的质因子必须包含$n$的质因子。若$1\lea,b$,则$a\timesb\gea+b$,所以我们就有了策略。将同一个质因......
  • P9451 [ZSHOI-R1] 新概念报数 题解
    目录DescriptionSolutionCodeDescription在此题中,对于一个数\(x\),若\(\texttt{popcount}(x)\geq3\)(即\(x\)在二进制下\(\texttt{1}\)的个数大于等于三时),那它是非法的,否则其为合法的。给定\(T\)个数,如果当前的数\(x\)是非法的,则输出No,Commander,否则输出第一个大于......