比赛链接
开了把vp,C降智导致浪费大量时间/dk/dk
A
贪心,几种凑 (10) 的方案的优先度是:((3,3,4),(3,3,2,2),(4,4,2),(2,2,2,2,2),(4,2,2,2))
ll a, b, c, ans;
void solve() {
read(a); read(b); read(c);
ll sum = 0;
ll t1 = Min(b/2, c+a/2);
sum = t1;
if(t1 > c) t1 -= c, c = 0, a -= 2 * t1;
else c -= t1;
ll t2 = Min(c/2, a);
a -= t2;
printf("%lld
", sum + t2 + a/5 + (a % 5 >= 3 && c % 2 == 1));
}
B
设 (f_i) 为 (([i,n],1)) 一条线段也没挂的最大挂绳子数。
按顺序枚举每一个绳子,然后用线段树快速转移这个 dp 即可。
C
把 (k) 能够把所有的 (A) 都添到 (max A) 的情况特判掉,这样答案只可能 (leq max A).
开个桶,用前缀和维护值域上的 (A) 的个数,(A) 的和,枚举每一个可能的答案 (x),然后枚举 (x) 的倍数,可以快速统计所需的最小代价。复杂度是调和级数的。
D
状压dp + 费用提前计算。
从前往后枚举 (i),设 (f_S) 为考虑集合 (S) 已经连在一起且排好序的代价,并且包括提前计算的费用,这里提前计算的费用是使得有一个数想加进来的时候之间按照插排的规则插入进来,走到这个段之前的代价已经在 (f) 里面算进去了。
这个提前计算的费用为多少?对于一个位置 (i) 如果不是最终的递增段,而是一个路人,那么递增段要经过它并且凑齐的最小代价是递增段在它左边多少和在它右边多少取个 (min),也就是 (min(pop\_count(S),k-pop\_count(S)))。
形象地:
(o...o...o..Delta..o...o...o..o)
假如 (Delta) 是当前枚举到的 (i),而 (o) 是最终要拼成连续段的位置,那么要不然左边所有的 (o) 越过 (Delta),要不然右边所有的 (o) 越过 (Delta),那么 (Delta) 处需要提前计算的费用就是两边 (o) 的个数取 (min).
E
感性理解一下,(lim_{n oinfty}f(n)=frac{1}{2}sum_{i<j}|A_i-A_j|),严谨的证明在这里。
离散化一下,在值域上开个线段树,维护值域区间有几个 (A),以及它们的和是多少,就能维护答案了。
F
不会。