从 2020.2.10 开始,我将在这里记下我所见过的所有(我没做出来的)结论题。。
[CF1299C] Water Balance
题意
给定长度为 n n n 的正整数组 a a a,一次操作被定义为将一个区间内的所有数变成这个区间的平均值。
设计若干次操作,使得最终的数组字典序尽量小。输出最后的数组。
数据范围: 1 ≤ n , a i ≤ 1 0 6 1\le n, a_i\le 10^6 1≤n,ai≤106,精度误差要求 ∣ a i − b i ∣ max ( 1 , b i ) ≤ 1 0 − 9 \frac{|a_i-b_i|}{\max(1,b_i)}\le 10^{-9} max(1,bi)∣ai−bi∣≤10−9。
题解
我们在平面坐标系中做出 n n n 个点 ( i , ∑ j = 1 i a j ) (i, \sum\limits_{j=1}^i a_j) (i,j=1∑iaj),一开始的线段是从第 i ( 1 ≤ i < n ) i (1\le i<n) i(1≤i<n) 到第 i + 1 i+1 i+1 个点连一条线段。
则最后得出的序列像上面的方法建,是原来序列的凸包。
所以求一个凸包即可。
代码
咕咕咕
[CF1305E] Kuroni and the Score Distribution
题意
构造整数数组 a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots, a_n a1,a2,⋯,an,满足
- 1 ≤ a 1 < a 2 < ⋯ < a n ≤ 1 0 9 1\le a_1<a_2<\cdots<a_n\le 10^9 1≤a1<a2<⋯<an≤109
- ∑ 1 ≤ i < j < k ≤ n [ a i + a j = a k ] = m \sum\limits_{1\le i<j<k\le n} [a_i+a_j=a_k]=m 1≤i<j<k≤n∑[ai+aj=ak]=m
数据范围: 1 ≤ n ≤ 5000 , 1 ≤ m ≤ 1 0 9 1\le n\le 5000, 1\le m\le 10^9 1≤n≤5000,1≤m≤109。
题解
其实是思博题,但我考场思路混乱,竟没想出来,,
首先我们应当从 1 开始每次递增 1 填,可以发现这样对答案的贡献为 0,0,1,1,2,2,3,3 …
然后如果发现再加一个就超过 m m m 了,由于下一个增量的值域是包括要增的数的,所以肯定能找到一个数放在这个位置。
现在的问题就是剩下的数怎么办呢?
设最后放的数为 x x x,我们只需要让接下来的数是 2 x + 1 , 3 x + 2 , 4 x + 3 , ⋯ 2x+1, 3x+2, 4x+3, \cdots 2x+1,3x+2,4x+3,⋯ 即可。
容易发现这样构造数一定不超过 1 0 9 10^9 109,而我们肯定从 1 每次递增 1 增长的是最快的,所以如果凑不出来就是凑不出来。
时间复杂度 O ( n ) O(n) O(n)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int N, M, a[5005];
int main() {
scanf("%d%d", &N, &M); int i, cnt = 0;
for (i = 1; i <= N; ++i) scanf("%d", &a[i]);
a[0] = 1;
for (i = 1; i <= N; ++i) {
if (!M) {
if (!cnt) cnt = a[i - 1] + 1;
a[i] = a[i - 1] + cnt;
}
else if (M >= (i - 1) / 2) a[i] = i, M -= (i - 1) / 2;
else { a[i] = 2 * i - 2 * M - 1, M = 0; }
}
if (M) puts("-1");
else {
for (i = 1; i <= N; ++i) printf("%d ", a[i]);
}
return 0;
}