UNR#1 选做

UOJ NOI Round #1 Day1

【UNR #1】争夺圣杯

考虑一个 (O(N^2)) 的暴力,从后往前维护每个位置往后的单调栈,然后维护一个差分数组,先枚举每个元素 (i),再枚举 (i) 往后的单调栈的每个元素 (x),只需要给差分数组上第 (x-i) 个位置加上 (st[x]-st[x-1]) 的权值即可。然后再在第 (n-i) 个位置上减去 (max_{j=i}^n(a_j)) 即可。

不难发现问题等价于:删除/加入一个关键点,所有关键点位置 (+1),给所有关键点上的权值加上 (v_i)

删除/加入总次数是 (O(N)) 级别的,每次相当于删除/加入一个元素的时候相当于是给差分数组上的一段区间加上 (v_i),直接维护一个二阶差分数组即可。

【UNR #1】合唱队形

考虑设 (f_i) 表示第 (i) 秒还没结束的概率,那么 (f_i) 的和就是结束时间的期望。

考虑怎么单独计算一个 (f_i),显然没一个位置合法不太好算,但是所有位置都合法很好计算。因此考虑容斥,枚举每一个位置往后是否合法,然后用子集容斥即可求解。容斥之后问题等价于给定 (n) 个数,每轮选择随机选择一个数再放回去,问 (i) 轮之后,给定的 (k) 个数都被选择过的概率。

都被选择过仍然不太好算,这里再套一层容斥,枚举有多少个没有被选择过,假设有 (x) 个没有被选择过,那么贡献是 ((-1)^xdbinom{k}{x}dfrac{(n-x)^i}{n^i})。设 (f(S)) 表示集合 (S) 往后全部匹配需要上多少节课。两层一起写出来就是:

[Ans=sum_{i=0}^{infty}sum_{S}(-1)^{|S|}sum_{x=0}^{f(S)}(-1)^xdbinom{f(S)}{x}dfrac{(n-x)^i}{n^i}=sum_{S}(-1)^{|S|}sum_{x=0}^{f(S)}(-1)^xdbinom{f(S)}{x}sum_{i=0}^{infty}dfrac{(n-x)^i}{n^i} ]

[Ans=sum_{S}(-1)^{|S|}sum_{x=0}^{f(S)}(-1)^xdbinom{f(S)}{x}dfrac{n}{x} ]

直接计算即可做到 (O(2^nn^2))。实际上真正的复杂度是 (O(2^{n-m}n)),如果我们得到了一个 (O(2^mn^2)) 的做法,那么均摊一下就是 (O(2^{frac{n}{2}}n^2))。于是接下来考虑一个 (O(2^mn^2)) 的做法。

考虑对于相同的 (f(S)),对答案的贡献是一样的,于是我们就只要求出 (f(S)=x) 的所有 (S)((-1)^{|S|}) 之和就可以了。发现每个元素相关的数只和前面 (m) 个数有关系,那么就显然可以状压了。

(dp_{i, j, k}) 表示考虑到第 (i) 个数,前 (m) 个数被选择的状态是 (j),总共有 (k) 个课程是必须上的,然后直接转移即可。

【UNR #1】果冻运输

提答题,咕了。

UOJ NOI Round #1 Day2

【UNR #1】Jakarta Skyscrapers

首先这个过程形似辗转相除法,那么就有了一个基本思路:首先必须要保证 (gcd(a, b)|c),然后分成两步,先求出 (gcd(a, b)),再求出 (c)

先假设 (gcd(a, b))(g)(c=kg),那么怎么通过 (g) 来求出 (c) 呢?考虑通过 (a-(a-c-c)) 三次操作,我们可以得到 (2c),接着有 (a-(a-2c-2c)) 两次操作可以得到 (4c),也就是可以通过 (3+2(n-1)) 次操作,可以得到 (2^nc),然后再将 (k) 二进制分组,先减后加即可(也就是 (a-(a-2^{a_1}c-2^{a_2}c-2^{a_3}c)) 类似物),每次操作次数 (3logn)

再考虑怎么求 (gcd(a, b)),这是一个辗转相除法,我们需要实现快速取模,不难发现也可以通过上述方式,实现取模,但是我们要取 (log) 次模,每次复杂度 (3log),那么整体复杂度就是 (O(3log^2n)),显然过不去。但是实际上 (log) 后面的值是 (dfrac{a}{b}),由于 (log(a)+log(b)=log(ab)),所以总复杂度也是 (O(3logn)) 的,总共 (6logn),大致是 (360) 次操作。

【UNR #1】奇怪的线段树

考虑到变黑的点一定是一个连通块,可以先把不合法情况特判掉。只要连通块的所有叶子节点合法,那么整个连通块就合法。

不难发现每次选择一定是选择一个叶子结点(只考虑连通块)所代表的区间,然后一定是选择一个左儿子和一个右儿子。

结论:假设 (u)(LCA) 的链为 (l_1)(v)(LCA) 的链为 (l_2),且 (u)(LCA) 左儿子的子树内,(v)(LCA) 右儿子的子树内,那么 (u) 一定是其父亲的右儿子,(v) 一定是其父亲的左儿子,且 (l_1) 上所有结点的右儿子均会被染黑,(l_2) 上所有的节点的左儿子均会被染黑。

有一个神奇的建图:考虑选择了某个点 (i) 之后,那么下一个满足 (l[j]=r[i]+1),且不和 (i) 是兄弟节点的 (j) 是确定且唯一的,也就是只要 (LCA) 的深度比 (j) 小,那么 (j) 节点也会被选择。那么我们将 (i) 连向 (j)。然后再将每个节点连向其左儿子,然后我们惊讶地发现,每一条路径都对应一种染色方案,且这张图是个 (DAG)(左端点不降)。

那么就只需要把必须经过的叶子节点拆点之后加一个 (1) 的下界,跑带上下界最小流即可。

【UNR #1】火车管理

首先显然可以线段树套线段树,在第二个线段树上线段树二分做到两个 (log)

首先考虑离线怎么做。维护一个位置 (x) 在每个时刻的数组,用线段树维护。不难发现相邻两个变化不大。查询就差分一下,查询历史版本和。区间加元素就拆成加元素和删元素,加元素就是把当前时间往后全部变成 (x),删元素就把当前元素往后全部变成当前元素往前一个的权值。

考虑在线做法:如果我们可以快速的查询单点弹栈之后元素是什么,那么就可以用一个支持区间覆盖和区间询问的线段树进行查询。

在建立一颗主席树,把覆盖的元素改一下,权值为修改的时间,然后和离线做法一样,当前位置弹栈之后,权值应该为当前栈顶修改时间减一时,这个点对应的权值。由于在这中间的时刻都不可能再被访问到,所以只需要改掉当前时刻该位置的权值即可。

原文地址:https://www.cnblogs.com/bcoier/p/14886992.html