闲话 20.9.20
闲话
吓死我了我还以为joke3579的闲话永久停更了。
不知道为什么 最近这些天一直在唱《non-breath oblige》
但是没有歌词 因此很抓狂 因为原曲很快我根本记不住词
哪位好心人给一下歌词(
话说饭最近似乎停更了
然后转职成了职业画家(
这是一张画!
好看!
话说他歌的pv都是他(以及勤奋的助手们)画的
饭还在发布《若能化作彗星》后拿这首歌的pv做例子讲了一下呢
事职业画家!
有哪位好心人能和我说一下饭的近况啊(
有新歌吗(多半没有吧我猜)
有那更好了
孩子瘾犯了
一道dp题(?)
给一棵 \(n\) 个点的 AVL树,节点权值即为编号。需要把它删到剩下 \(k\) 个点。构造一种方案使得删完后的树还是 AVL 树且字典序最小。输出每个点在该方案下的存留情况。
\(n \le 10^5, 1\le k \le n\)。
这题有 \(O(n\log n)\) 的做法但我不会。讲一下 \(O(n \log^2n)\) 的。
首先贪一下,按照先序遍历枚举节点通过dp查看可达性。
具体地,设 \(f_{i,j}\) 为在原树形态的基础上以 \(i\) 为根节点,构成一棵深度为 \(j\) 的 AVL 需要几个节点。容易写出dp方程:
枚举节点,将该节点与其所有祖先标记为必选,标记过程中更新标记对象父节点的dp数组。随后对根节点进行判断。如果在钦定该节点必选的情况下存在一种深度 \(d\) 使得 \(f_{rt,d} \le k\),该节点就可以被选择。
因此有标记 \(i\) 节点为必选的方式:赋 \(f_{i,0}, f_{i,1}\) 为 \(\inf\)。
若不可被选择,需要返回未选的情况。
对单个节点的判断是 \(O(\text {树高}^2)\) 的。由于是 AVL 树,因此树高为 \(O(\log n)\)。
code
#include <bits/stdc++.h>
#define rep(i,a,b) for (register int (i) = (a); (i) <= (b); ++(i))
#define pre(i,a,b) for (register int (i) = (a); (i) >= (b); --(i))
using namespace std;
#define int long long
const int N = 5e5 + 10;
int n, k, t1, rt, u, ans, flag[N], f[N][25], g[N][25];
#ifdef ONLINE_JUDGE
char buf[1<<21], *p1 = buf, *p2 = buf; inline char getc() { return (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<21, stdin), p1 == p2) ? EOF : *p1++); }
#define getchar getc
#endif
template <typename T> inline void get(T & x){
x = 0; char ch = getchar(); bool f = false; while (ch < '0' or ch > '9') f = f or ch == '-', ch = getchar();
while (ch >= '0' and ch <= '9') x = (x<<1) + (x<<3) + (ch^48), ch = getchar(); f && (x = -x);
} template <typename T, typename ... Args> inline void get(T & x, Args & ... _Args) { get(x); get(_Args...); }
struct node {
int fa, ls, rs, dp, cnt;
#define ls(p) avl[p].ls
#define rs(p) avl[p].rs
#define fa(p) avl[p].fa
#define dep(p) avl[p].dp
#define cnt(p) avl[p].cnt
#define isls(p) (p == ls(fa(p)))
} avl[N];
void upd(int u) {
f[u][0] = f[u][1] = 1e9;
for (int i = 2; i <= dep(u); i++) f[u][i] = min( f[ls(u)][i - 1] + min( f[rs(u)][i - 1] , f[rs(u)][i - 2] ) + 1 , f[ls(u)][i - 2] + f[rs(u)][i - 1] + 1 );
}
void dfs(int u) {
if (ls(u)) dfs(ls(u));
if (rs(u)) dfs(rs(u));
dep(u) = max(dep(ls(u)), dep(rs(u))) + 1;
upd(u);
f[u][0] = 0, f[u][1] = 1;
}
bool check(int u) {
if (flag[u]) return 1;
flag[u] ++;
for (int i = 0; i <= dep(u); i++) g[u][i] = f[u][i];
f[u][0] = 1e9;
while (u != rt) {
u = fa(u);
for (int i = 0; i <= dep(u); i++) g[u][i] = f[u][i];
upd(u); flag[u] ++;
} int mn = 1e9;
for (int i = 1; i <= dep(rt); i++) mn = min(mn, f[rt][i]);
return mn <= k;
}
void roll_back(int u) {
flag[u] --;
for (int i = 0; i <= dep(u); i++) f[u][i] = g[u][i];
while (u != rt) {
u = fa(u);
for (int i = 0; i <= dep(u); i++) f[u][i] = g[u][i];
flag[u] --;
}
}
signed main() {
get(n, k);
rep(i,1,n) {
get(t1);
if (t1 == -1) rt = i;
else {
if (t1 > i) ls(t1) = i;
else rs(t1) = i;
} fa(i) = t1;
} memset(f, 0x3f, sizeof f);
rep(i,0,n) f[i][0] = 0;
dfs(rt);
rep(i,1,n) {
if (check(i)) cout << 1;
else cout << 0, roll_back(i);
}
return 0;
}
置换环
定义在集合 \(\mathbb{P}\) 上的置换为一个 \(\mathbb{P}\rightarrow \mathbb{P}\) 的双射 \(f\)。容易发现,任何一个置换 \(f\) 都可以被大小为 \(\mathbb{|P|}\) 的排列 \(p\) 表示。由置换的定义自然导出单位置换 \(e\) 与置换的复合运算。定义 \(f^k\) 为 \(f\) 自复合 \(k\) 次后得到的置换。对于置换 \(f\),若 \(f^k = e\) 且 \(k(k>0)\) 极小,就称 \(k\) 是 \(f\) 的周期。
对于一个 \(\mathbb{P}\) 上的置换 \(f\) 对应的排列 \(p\) ,我们在一个 \(\mathbb{|P|}\) 个点的图上,由 \(i\) 向 \(p_i\) 连边,会得到一个由环构成的有向图,这称作 \(f\) 的置换环图,其中的环称作 \(f\) 的一个置换环。
断言:\(f\) 的周期为所有置换环大小的最小公倍数。
证明:
当 \(f\) 仅有一个置换环时定理显然成立,因为每个节点都需要环大小长度的遍历后才能回到其本身。
首先考察 \(f\) 仅有两个置换环的情况。设这两个环的大小为 \(a\) 与 \(b\)。当 \(a = b\) 时退化到一个置换环的情况,显然成立。因此考虑 \(a \neq b\)。不妨设 \(a < b\)。
我们需要的是同时遍历完两个环的最小长度。现讨论遍历两个环的过程中位置的同步度。不妨设遍历 \(\frac{a}{\text{period}(a,b)}\) 次 \(b\) 环后 \(a\) 环被遍历完。容易发现定义是良的,因为当 \(\text{period}(a,b) = 1\) 时显然成立。
考虑当遍历完一个环后在另一个环上余下的长度 \(b - a\)。
若 \(b - a \mid a\),那 \(\text{period}(a,b) = b - a\)。因此有
考虑 \(b - a\nmid a\)。由于现在需要让 \(a\) 与 \(b - a\) 同步,因此我们现在需要解决的子问题表述出了 \(\text{period}(a,b) = \text{period}(a,a-b)\)。根据更相减损术,这表明 \(\text{period}(a,b) = \gcd(a,b)\)。这也表示了 \(b - a \mid a\) 是当前情况的特解。
因此当只存在两个环时有
同时这给出了将两个大小任意的环归约成一个等价环的方法。
对于 \(k(k >2)\) 个环的情况,可以先将两个环归约为一个环,这就转化到了 \(k-1\) 个环的情况。根据数学归纳法,该断言成立。\(\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\quad\square\)
以下是博客签名,与正文无关。
请按如下方式引用此页:
本文作者 joke3579,原文链接:https://www.cnblogs.com/joke3579/p/chitchat220920.html。
遵循 CC BY-NC-SA 4.0 协议。
请读者尽量不要在评论区发布与博客内文完全无关的评论,视情况可能删除。