首页 > 其他分享 >CF1053E-Euler Tour题解

CF1053E-Euler Tour题解

时间:2023-07-27 09:36:28浏览次数:39  
标签:suf int 题解 CF1053E 样例 Tour 2n acorns Euler

前言

还是一道神仙题

很难想

题面

luogu上copy的

样例解释懒得翻,我觉得应该都看得懂样例吧。

题面翻译

现有一棵 \(n\) 个点的形态未知的树,给定其长度为 \(2n-1\) 的欧拉序的一部分

请根据给出的残缺的欧拉序还原出一个完整的欧拉序或判断不存在这样的树

输入中用非零数字表示欧拉序被确定了,而 \(0\) 表示这位没有被确定

\(n\le 5\times 10^5\)

简化题意

现在给你一个欧拉序,有一些位置没有确定。现在让你判断是否存在这样的合法的欧拉序,如果有,就要输出一种合法方案。

题目描述

Euler is a little, cute squirrel. When the autumn comes, he collects some reserves for winter. The interesting fact is that Euler likes to collect acorns in a specific way. A tree can be described as $ n $ acorns connected by $ n - 1 $ branches, such that there is exactly one way between each pair of acorns. Let's enumerate the acorns from $ 1 $ to $ n $ .

The squirrel chooses one acorn (not necessary with number $ 1 $ ) as a start, and visits them in a way called "Euler tour" (see notes), collecting each acorn when he visits it for the last time.

Today morning Kate was observing Euler. She took a sheet of paper and wrote down consecutive indices of acorns on his path. Unfortunately, during her way to home it started raining and some of numbers became illegible. Now the girl is very sad, because she has to present the observations to her teacher.

"Maybe if I guess the lacking numbers, I'll be able to do it!" she thought. Help her and restore any valid Euler tour of some tree or tell that she must have made a mistake.

输入格式

The first line contains a single integer $ n $ ( $ 1 \leq n \leq 5 \cdot 10^5 $ ), denoting the number of acorns in the tree.

The second line contains $ 2n - 1 $ integers $ a_1, a_2, \ldots, a_{2n-1} $ ( $ 0 \leq a_i \leq n $ ) — the Euler tour of the tree that Kate wrote down. $ 0 $ means an illegible number, which has to be guessed.

输出格式

If there is no Euler tour satisfying the given description, output "no" in the first line.

Otherwise, on the first line output "yes", and then in the second line print the Euler tour which satisfy the given description.

Any valid Euler tour will be accepted, since the teacher doesn't know how exactly the initial tree looks.

样例 #1

样例输入 #1

2
1 0 0

样例输出 #1

yes
1 2 1

样例 #2

样例输入 #2

4
1 0 3 2 0 0 0

样例输出 #2

yes
1 4 3 2 3 4 1

样例 #3

样例输入 #3

5
0 1 2 3 4 1 0 0 0

样例输出 #3

no

提示

An Euler tour of a tree with $ n $ acorns is a sequence of $ 2n - 1 $ indices of acorns. such that each acorn occurs at least once, the first and the last acorns are same and each two consecutive acorns are directly connected with a branch.

解法

这道题便思路 首先我们想一下欧拉序(我们用\(a\)表示)是怎么样的:

  1. \(a_1 = a_{2n - 1}\)
  2. \(\forall a_l = a_r, 2 | r - l(即是偶数),且出现了\frac{r - l}{2} + 1\)
    这一点自己举几个例子应该可以马上理解
  3. 所有 $a_l = a_r $ 的区间构成的集合 \(S\),\(S\) 必然可以构造出纯的构造关系,不可能存在 $ i ≠ j $
  4. \(\forall 1\leq i\leq2n-1,1\leq a_i \leq n\)

现在我们不妨设有一个区间\([l, r]\), 因为满足\(a^{'}_l = a ^{'} _r\)的区间就一定代表了一颗子树,所以我们不妨先递归处理以后再用缩点的思想,缩成一个点,这一个序列变成了\(a^{''}_l\),就可以继续了。

对于每一个\(i\), 我们预处理出下一个和\(a_i\)相等的下标,也就是右端点,这样我们在缩点的时候可以顺面判断一下条件3,就是包含关系那个。

现在\([l, r]\) 就不存在权值相同的点,如果出现了少于\(\frac{r - l}{2} + 1\)种,我们就直接暴力填最前面。一个非常显然的是,种类数目超过\(\frac{r - l}{2} + 1\)种肯定就是不对了。

现在我们想一下长度为3的区间。经过我们的深思熟虑,可以得到可能是如下几种:

  1. xy0
  2. 0yx

这两种我们在进行补全都可以变成xyx的形式,然后在缩点缩成x的形式。

如果这样填完还会有空的点,不妨将剩下的位置填上这颗子树的root。

正确性的证明是从别的博客里面借鉴过来的(其实我这个构造方法也是那里学的,教练讲得有点潦草,我看了题解才懂得)

考虑这样做的正确性:
若不存在两个不为0的位置相邻,区间的首尾一定已经填入数字且相邻的两个已经填入数字的位置中恰好隔着一个0,此时将剩下的位置填成这棵子树的根显然正确;
若存在两个不为0的位置相邻,缩点之后不为0的位置减少了1,为0的位置也减少了1,两者的差不变,因此可以看做是递归下去,直到出现第1种情况。

特别的,我们对于\([1, 2n - 1]\) 要保证首尾相同,这样才是一个合法的序列。我们对这个进行一下分类讨论:

  1. \(a_1, a_{2n-1} > 0\), \(a_1 ≠ a_{2n - 1}\) 非法序列
  2. \(a_1, a_{2n - 1} > 0, a_1 = a_{2n - 1}\) 合法序列,直接递归就行了
  3. 若\(a_1 > 0\) 或 \(a_{2n - 1} > 0\) 把另外一个填成和那个有的一样的就行了
  4. 若\(a_1 = a_{2n - 1} = 0\),按照之前的那个算法,从左到右合并能够保证首尾相同并且没有剩余位0.

其实这个方法适用于所有的区间\([l, r]\)
然后我们用链表实现(数组模拟链表,不建议写指针),复杂度\(O(n)\)

代码

这份代码是我之前写的 压行了 但是我觉得还是比较整洁的 应该还是可以看的

如果你觉得看起来不是很舒服 非常抱歉 自行换个行 谅解一下

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

# define N 1000005
int n, m, now = 1, a[N], vis[N], nxt[N], pre[N], suf[N];

inline void Fail() { puts("no"), exit(0); }
inline int Get_ () { 
	while (vis[now]) ++now; 
	if (now > n) Fail(); 
	vis[now] = 1; return now; 
}
inline void del (int l, int r) { int tl = pre[l], tr = suf[r]; suf[tl] = tr, pre[tr] = tl; }

inline void Merge (int l, int r, int & x) {
	while (x > l && suf[suf[x]] && suf[suf[x]] <= r && !a[x] && a[suf[x]] && a[suf[suf[x]]]) 
		a[x] = a[suf[suf[x]]], del (suf[x], suf[suf[x]]), x = pre[pre[x]];
	while (x > l && suf[suf[x]] && suf[suf[x]] <= r && a[x] && a[suf[x]] && !a[suf[suf[x]]]) 
		a[suf[suf[x]]] = a[x], del (suf[x], suf[suf[x]]), x = pre[pre[x]];
}

inline void solve (int l, int r) {
# define rep for (int i = l ; i <= r; i = suf[i])
	if (r - l & 1) Fail(); 
	rep while(nxt[i]) { 
		if (nxt[i] > r) Fail(); solve(suf[i], pre[nxt[i]]); 
		del (suf[i], nxt[i]); nxt[i] = nxt[nxt[i]]; 
	}
	int num1 = 0, num2 = 0, rt = a[pre[l]]; rep num1 += a[i] > 0, ++num2;
	num2 = (num2 >> 1) + 1; if (num1 > num2) Fail(); num2 -= num1;
	for (int i = l; i <= r && num2; i = suf[i]) { if (!a[i]) a[i] = Get_ (), --num2; } 
	rep  Merge(l - 1, r, i); rep if (!a[i]) a[i] = rt;
}

signed main() {
	scanf ("%d", &n); if (n == 1) return puts("yes\n1"), 0; 
	m = (n << 1) - 1; for (int i = 1; i <= m; ++i) scanf ("%d", &a[i]); 
	for (int i = 2; i <= m; ++i) if (a[i] && a[i - 1] && a[i] == a[i - 1]) Fail();
	if (a[1] && a[m] && a[1] != a[m]) Fail(); a[1] = a[m] = a[1] | a[m]; 
	for (int i = 0; i <= m + 1; ++i) pre[i] = i - 1, suf[i] = i + 1; pre[0] = 0; 
	for (int i = m; i >= 1; --i) if (a[i]) nxt[i] = vis[a[i]], vis[a[i]] = i;
	solve(1, m), puts("yes"); for (int i = 1; i <= m; ++i) printf ("%d ", a[i]); return 0;
}

标签:suf,int,题解,CF1053E,样例,Tour,2n,acorns,Euler
From: https://www.cnblogs.com/georgeyucjr/p/17583118.html

相关文章

  • P3704 [SDOI2017] 数字表格 题解
    一、题目描述:用$f_i$表示斐波那契数列的第$i$项,那么有:$f_0=0,f_1=1;f_n=f_{n-1}+f_{n-2},n\ge2$现在有一个$n$行$m$列的数字表格,第$i$行第$j$列的数字是$f_{\gcd(i,j)}$。求这个表格所有数的乘积。共有$T$组数据,答案对$10^9+7$取模。......
  • Xcode12 开发12.5.7版本IOS的问题解决
    1.xcode12默认是创建的工程是14.2,所以需要修改一下工程版本。点击项目最上面的蓝色文件就可以打开下面的界面了。2.安装app之后,界面黑屏。解决方法如下:在AppDelegate.h中:#import<UIKit/UIKit.h>@interfaceAppDelegate:UIResponder<UIApplicationDelegate>//增......
  • [ARC143B] Counting Grids 题解
    CountingGrids题目大意将\(1\simn^2\)填入\(n\timesn\)的网格\(A\)中,对于每个格子满足以下条件之一:该列中存在大于它的数。该行中存在小于它的数。求方案数。思路分析首先有一个比较显然的结论:对于一个不合法的方案,有且仅有一个数不满足任何一个条件。考虑......
  • [ABC308G] Minimum Xor Pair Query 题解
    MinimumXorPairQuery题目大意维护一个序列,支持动态插入,删除,查询最小异或对。思路分析看到查询最小异或对首先想到01Trie,但01Trie不支持删除,考虑暴力套一个线段树分治。需要预处理出每个元素的存活区间,这里使用了map<int,vector<int>>。注意,有的元素会存活到最后,需要特......
  • 网络瘤24题解+总结
    目录网络流24题太空飞行计划最大权闭合子图模型最小路径覆盖问题Trick总结网络流24题顺序主观决定太空飞行计划教训:(开始想费用流,搞半天出不来)网络流解决最大/小费用问题,要么最小割最大流,要么最小费用流最小费用流的前提是最大流,所以在有一些点可以不取换最优代价的时候,是......
  • P5369 [PKUSC2018] 最大前缀和 题解
    传送门题目大意给定一个序列,求任意重排\(n!\)中情况所以的最大非空前缀和的和。模\(998244353\)。\(n\e20\),\(\sum|a_i|\le10^9\)题目解析考虑最大前缀和的性质,有:对于最大前缀和部分,所有的真后缀大于等于零。(最大前缀和可能小于零)对于不在最大前缀和的后半部分,所......
  • [JOI 2022 Final] 自学 题解
    洛谷传送门1.题意简述:一个学期有\(N\)天\(N*M\)节课,每天的第\(i\)节课可以选择效果\(a_i\)的学习与\(b_i\)的自习。问应如何安排每节课,使所有功课最小值最大?2.思路:这道题想直接模拟非常麻烦,但是如果我们能够灵活运用二分算法,这道题就非常简单了。考虑到数据范围较......
  • luogu P9474 [yLOI2022] 长安幻世绘 详细题解
    原题:P9474[yLOI2022]长安幻世绘看到很多大佬的题解直接讲了做法,本蒟蒻看得不是很懂,调了很久才把这题做出来,于是写了这篇比较详细的题解谈一下我做这题从头到尾的思路,希望对各位有帮助qwq。思路我们首先思考这样一个问题,如果已经知道最终答案对应的最大值和最小值,又不知道题......
  • AT_agc017_b 题解
    洛谷链接&Atcoder链接本篇题解为此题较简单做法,请放心阅读。题目简述一共有\(n\)个格子,给定两个整数\(A,B\)分别位于第\(1\)和第\(n\)格,中间有\(n−2\)个空格。询问是否存在一种填数方案满足任意相邻两个数之差的绝对值在\([C,D]\)之间。依次输入\(n,a,b,c,d\)......
  • AT_arc149_a 题解
    洛谷链接&Atcoder链接本篇题解为此题较简单做法及较少码量,并且码风优良,请放心阅读。题目简述求满足以下条件的小于\(10^n\)数最大是多少?每一位数字均相同;是\(m\)的倍数。数据范围:\(1\len\le10^5\),\(1\lem\le10^9\)。思路首先每位数字都相同很好满足,仅需......