T1
给定 nnn 个数 {an}\{a_n\}{an},每次操作可以选择一个 i∈[1,n]i\in [1,n]i∈[1,n] 使得 ai←ai−1a_i\gets a_i-1ai←ai−1。求最少操作次数使得 aaa 中除了 000 以外其他值至多出现 111 次。
n≤2×105n\le 2\times 10^5n≤2×105,ai∈[0,106]a_i\in [0,10^6]ai∈[0,106]。
直接在值域上考虑,令 tit_iti 表示值为 iii 的元素个数,从大往小考虑,若 ti>1t_i>1ti>1 那么需要执行 ti−1t_i-1ti−1 次操作令 ti←1t_i\gets 1ti←1,与此同时会令 ti−1←ti−1+ti−1t_{i-1}\gets t_{i-1}+t_i-1ti−1←ti−1+ti−1;一直这么推下去推到 000 为止即可。如果值域大一些直接考虑有值的 nnn 个位置即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define open(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
const int maxn = 1e6 + 5;
ll t[maxn]; int n, a[maxn];
int main() {
open(seq);
scanf("%d", &n);
for (int i = 1; i <= n; i ++)
scanf("%d", &a[i]), t[a[i]] ++;
ll ans = 0;
for (int i = 1e6; i > 0; i --)
if (t[i] > 1)
ans += t[i] - 1, t[i - 1] += t[i] - 1;
printf("%lld\n", ans);
return 0;
}
T2
给定 nnn,构造一个仅包含 X,Y,D\texttt{X},\texttt{Y},\texttt{D}X,Y,D 三种字符的字符串使得 XYD\texttt{XYD}XYD 这个子序列恰好出现 nnn 次。要求串长 ≤6000\le 6000≤6000。
n≤109n\le 10^9n≤109。
赛时糖丸了,推了一个关于平方的做法,差点就被我发现了。一个简单的做法是考虑在 X\texttt{X}X 后面放 YD\texttt{YD}YD 的贡献,发现若放了 nnn 个则产生了 n(n+1)2\cfrac{n(n+1)}{2}2n(n+1) 个 XYD\texttt{XYD}XYD 子序列(可能往上往下有出入,大概长这样),于是我们考虑把 nnn 拆成这么几段,先放一个由若干段 YD\texttt{YD}YD 循环组成的串,然后在对应位置插入若干个 X\texttt{X}X 即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2005;
#define ll long long
#define open(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
ll a[maxn];
int main() {
open(xyd);
int n, m; scanf("%d", &n);
for (m = 1; m <= 2000; m ++)
if (a[m - 1] + m > n) break;
else a[m] = a[m - 1] + m;
for (m --; m > 0; m --, putchar('Y'), putchar('D'))
for (; a[m] <= n; n -= a[m]) putchar('X');
return 0;
}
T3
给定两个长度为 nnn 的序列 x,yx,yx,y,再给定 mmm 个长度为 nnn 的序列,对于第 iii 个序列 aia_iai 选择以下操作之一进行:
- 对于所有 j∈[1,n]j\in[1,n]j∈[1,n],令 xj←max(xj,ai,j)x_j\gets \max(x_j,a_{i,j})xj←max(xj,ai,j)。
- 对于所有 j∈[1,n]j\in[1,n]j∈[1,n],令 yj←max(yj,ai,j)y_j\gets \max(y_j,a_{i,j})yj←max(yj,ai,j)。
要求按顺序操作,求操作后最大的 ∑i=1nxi+yi\sum^n_{i=1}x_i+y_i∑i=1nxi+yi。
n≤10n\le 10n≤10,m≤105m\le 10^5m≤105。
先拼了一档 m≤20m\le 20m≤20 的暴搜做法,然后又拼了一个乱搞做法:每次比较 x,yx,yx,y 产生的增量,哪个多操作哪个,最终骗到 72pts72\mathrm{pts}72pts。然后一种可行解是随机化,正确率还挺高。
T4
显然最小的取法就是从每个集合中取一个最小值求和,我们设这个最优值为 ansansans。考虑其可能的后几个略小一些的状态。我们将每个集合按照次小值减最小值的差从小到大排序,每个集合内部按从小到大排序。假设当前状态 {i,j,w}\{i,j,w\}{i,j,w} 表示枚举到第 iii 个集合中的第 jjj 个数,考虑将 ansansans 中第 iii 个集合取的数更换为 jjj,更换后的答案为 www。令 c(i,j)c(i,j)c(i,j) 表示集合 iii 中第 jjj 大的值,最初始的状态即为 {1,2,ans−c(1,1)+c(1,2)}\{1,2,ans-c(1,1)+c(1,2)\}{1,2,ans−c(1,1)+c(1,2)}。对于每个状态会有三个可能的分支:
- 如果 j<sizij<siz_ij<sizi,则一种可能的选择即为放弃更换为 jjj,考虑更换为 j+1j+1j+1。新的状态为 {i,j+1,w−c(i,j)+c(i+j)}\{i,j+1,w-c(i,j)+c(i+j)\}{i,j+1,w−c(i,j)+c(i+j)}。
- 如果 iii 不是最后一个集合:
- 一种可能的选择即为决定更换为 jjj,开始考虑 i+1i+1i+1 集合的选择。新的状态为 {i+1,2,w−c(i+1,1)+c(i+1,2)}\{i+1,2,w-c(i+1,1)+c(i+1,2)\}{i+1,2,w−c(i+1,1)+c(i+1,2)}。
- 另外,如果 j=2j=2j=2,则一种可能的选择即为放弃更换 iii 中的元素,直接考虑 i+1i+1i+1 集合的选择。新的状态为 {i+1,2,w−c(i,2)+c(i,1)−c(i+1,1)+c(i+1,2)}\{i + 1,2,w - c(i,2) + c(i,1) - c(i+1,1) + c(i+1,2)\}{i+1,2,w−c(i,2)+c(i,1)−c(i+1,1)+c(i+1,2)}。
开一个优先队列记录这些状态,从中取 kkk 轮即为答案。