垃圾ACMer的暑假训练220719

垃圾ACMer的暑假训练220719

Codeforces

Codeforces Round #808 (Div. 2) D. Difference Array

原题指路:https://codeforces.com/contest/1708/problem/D

题意

给定一个长度为 n n n的非负整数序列 a a a,保证 a a a非降序排列.每次操作,构造一个新序列 b i = a i + 1 − a i    ( 1 ≤ i ≤ n ) b_i=a_{i+1}-a_i\ \ (1\leq i\leq n) bi=ai+1ai  (1in),并将 b b b非降序排列,将 b b b视为新的 a a a,序列长度变为 ( n − 1 ) (n-1) (n1).进行 ( n − 1 ) (n-1) (n1)次操作后,输出序列中剩下的一个整数.

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据第一行输入整数 n    ( 2 ≤ n ≤ 1 e 5 ) n\ \ (2\leq n\leq 1\mathrm{e}5) n  (2n1e5).第二行输入 n n n个整数 a 1 , ⋯   , a n    ( 0 ≤ a 1 ≤ ⋯ ≤ a n ≤ 5 e 5 ) a_1,\cdots,a_n\ \ (0\leq a_1\leq\cdots\leq a_n\leq 5\mathrm{e}5) a1,,an  (0a1an5e5).数据保证所有测试数据的 n n n之和不超过 2.5 e 5 , a i 2.5\mathrm{e}5,a_i 2.5e5,ai之和不超过 5 e 5 5\mathrm{e}5 5e5.

对每组测试数据,输出进行 ( n − 1 ) (n-1) (n1)次操作后序列中剩下的一个整数.

思路

S = ∑ i = 1 n a i \displaystyle S=\sum_{i=1}^n a_i S=i=1nai,则它在每次操作后会改变.进行一次操作后对 a a a升序排列,忽略所有为 0 0 0的项,注意到 n − 1 + a n ≤ S    ( a i ≥ 1 ) n-1+a_n\leq S\ \ (a_i\geq 1) n1+anS  (ai1),即 n − 1 ≤ S − a n n-1\leq S-a_n n1San恒成立.

进行一次操作后, S = a n − a 1 ≤ a n S=a_n-a_1\leq a_n S=ana1an,则每次操作花费 O ( n log ⁡ n ) O(n\log n) O(nlogn)的时间排序,并至少将 S S S减少 ( n − 1 ) (n-1) (n1).第一次操作后, S = O ( a n ) S=O(a_n) S=O(an).总时间复杂度 O ( A log ⁡ A ) O(A\log A) O(AlogA),其中 A = max ⁡ { n , a n } A=\max\{n,a_n\} A=max{n,an},暴力模拟即可.

代码
const int MAXN = 1e5 + 5;
int a[MAXN];

int main() {
	CaseT{
		int n; cin >> n;
		int pos = -1;
		for (int i = 1; i <= n; i++) {
			cin >> a[i];
			if (pos == -1 && a[i]) pos = i;
		}
		pos--;  // 第一个非零数与0也要作差,故pos--
		
		while (n > 1) {
			for (int i = max(1, pos); i < n; i++) a[i] = a[i + 1] - a[i];
			n--;

			sort(a + pos, a + n + 1);
			pos = upper_bound(a + 1, a + n + 1, 0) - (a + 1);
			if (pos == n - 1) break;
		}
		cout << a[n] << endl;
	}
}


Codeforces Round #809 (Div. 2) C. Qpwoeirut And The City

原题指路:https://codeforces.com/contest/1706/problem/C

题意

编号 1 ∼ n 1\sim n 1n的楼排成一行,其中第 i i i座楼的高度为 h i h_i hi.称一座楼是cool的,如果它的高度严格大于其左右的楼的高度,显然首尾的楼不能是cool的.现可选择一些楼增加整数的高度,使得cool的楼最多,求增加的高度之和的最小值.

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据第一行输入整数 n    ( 3 ≤ n ≤ 1 e 5 ) n\ \ (3\leq n\leq 1\mathrm{e}5) n  (3n1e5).第二行输入 n n n个整数 h 1 , ⋯   , h n    ( 1 ≤ h i ≤ 1 e 9 ) h_1,\cdots,h_n\ \ (1\leq h_i\leq 1\mathrm{e}9) h1,,hn  (1hi1e9).数据保证所有测试数据的 n n n之和不超过 2 e 5 2\mathrm{e}5 2e5.

对每组测试数据,输出使得cool的楼最多时增加的高度之和的最小值.

思路

显然cool的楼最多有 ⌊ n − 1 2 ⌋ \left\lfloor\dfrac{n-1}{2}\right\rfloor 2n1座,且 n n n为奇数时方案唯一,每两座cool的楼间相隔 1 1 1座楼.

n n n为偶数时,可能会出现两座cool的楼间相隔 2 2 2座楼的情况.注意到最后一个cool的楼只能是第 ( n − 1 ) (n-1) (n1) ( n − 2 ) (n-2) (n2)座, d p [ i ] dp[i] dp[i]表示楼 i i i是最后一个cool的楼的最小代价,则 a n s = min ⁡ { d p [ n − 1 ] , d p [ n − 2 ] } ans=\min\{dp[n-1],dp[n-2]\} ans=min{dp[n1],dp[n2]}.

从第 2 2 2座楼开始,偶数号的cool楼只能与前面的楼相隔 1 1 1座楼,而下标为奇数号的cool楼能与前面的楼相隔 1 1 1 2 2 2座楼.

代码
int main() {
	CaseT{
		int n; cin >> n;
		vl h(n + 1);
		for (int i = 1; i <= n; i++) cin >> h[i];

		ll ans = 0;
		if (n & 1) {
			for(int i = 2; i <= n; i += 2) ans += max((ll)0, max(h[i - 1], h[i + 1]) - h[i] + 1);
		}
		else {
			vl dp(n + 1);  // dp[i]表示楼i是最后一个cool的最小代价
			for (int i = 2; i < n; i++) {
				int tmp = max((ll)0, max(h[i - 1], h[i + 1]) - h[i] + 1);

				if (i & 1) dp[i] = min(dp[i - 2], dp[i - 3]) + tmp;  // 奇数位,与当前隔1、2取min
				else dp[i] = dp[i - 2] + tmp;  // 偶数位只能隔1
			}
			ans = min(dp[n - 1], dp[n - 2]);  // 最后一个cool的楼只能是n-1或n-2
		}
		cout << ans << endl;
	}
}


Codeforces Round #809 (Div. 2) D1. Chopping Carrots (Easy Version)

原题指路:https://codeforces.com/contest/1706/problem/D1

题意 ( 4   s ) (4\ \mathrm{s}) (4 s)

给定一个长度为 n n n的整数序列 a 1 , ⋯   , a n a_1,\cdots,a_n a1,,an和整数 k k k,定义一个整数序列 p 1 , ⋯   , p n    ( 1 ≤ p i ≤ k ) p_1,\cdots,p_n\ \ (1\leq p_i\leq k) p1,,pn  (1pik)的价值为 max ⁡ 1 ≤ i ≤ n ⌊ a i p i ⌋ − min ⁡ 1 ≤ i ≤ n ⌊ a i p i ⌋ \displaystyle\max_{1\leq i\leq n}\left\lfloor\dfrac{a_i}{p_i}\right\rfloor-\min_{1\leq i\leq n}\left\lfloor\dfrac{a_i}{p_i}\right\rfloor 1inmaxpiai1inminpiai.

t    ( 1 ≤ t ≤ 100 ) t\ \ (1\leq t\leq 100) t  (1t100)组测试数据,每组测试数据第一行输入整数 n , k    ( 1 ≤ n , k ≤ 3000 ) n,k\ \ (1\leq n,k\leq 3000) n,k  (1n,k3000),第二行输入 n n n个整数 a 1 , ⋯   , a n    ( 1 ≤ a 1 ≤ a 2 ≤ ⋯ ≤ 3000 ) a_1,\cdots,a_n\ \ (1\leq a_1\leq a_2\leq\cdots\leq 3000) a1,,an  (1a1a23000).数据保证所有测试数据的 n n n之和不超过 3000 3000 3000.

对每组测试数据,输出序列 p p p的最小价值.

思路

注意到 v = min ⁡ 1 ≤ i ≤ n ⌊ a i p i ⌋ \displaystyle v=\min_{1\leq i\leq n}\left\lfloor\dfrac{a_i}{p_i}\right\rfloor v=1inminpiai p i > a i p_i>a_i pi>ai时取 0 0 0,而序列 a a a升序,故只需枚举 v v v 0 0 0 a 1 a_1 a1,构造一个 min ⁡ 1 ≤ i ≤ n ⌊ a i p i ⌋ = v \displaystyle \min_{1\leq i\leq n}\left\lfloor\dfrac{a_i}{p_i}\right\rfloor=v 1inminpiai=v的序列 p : p i = min ⁡ { k , ⌊ a i v ⌋ }    ( v ≠ 0 ) p:p_i=\min\left\{k,\left\lfloor\dfrac{a_i}{v}\right\rfloor\right\}\ \ (v\neq 0) p:pi=min{k,vai}  (v=0);若 v = 0 v=0 v=0,取 p i = k p_i=k pi=k.此时 1 ≤ p i ≤ k , v ≤ ⌊ a i p i ⌋ 1\leq p_i\leq k,v\leq\left\lfloor\dfrac{a_i}{p_i}\right\rfloor 1pik,vpiai, a n s ans ans即所有 max ⁡ 1 ≤ i ≤ n ⌊ a i p i ⌋ − v \displaystyle\max_{1\leq i\leq n}\left\lfloor\dfrac{a_i}{p_i}\right\rfloor-v 1inmaxpiaiv的最小值.时间复杂度 O ( n ⋅ a 1 ) O(n\cdot a_1) O(na1).

代码
int main() {
	CaseT{
		int n,k; cin >> n >> k;
		vi a(n + 1);
		for (int i = 1; i <= n; i++) cin >> a[i];

		if (n == 1) {
			cout << 0 << endl;
			continue;
		}

		int maxnum = -INF, minnum = INF;
		for (int i = 1; i <= n; i++) {  // v=0时,取p_i=k
			maxnum = max(maxnum, a[i] / k);
			minnum = min(minnum, a[i] / k);
		}
		int ans = maxnum - minnum;

		for (int v = 1; v <= a[1]; v++) {
			maxnum = -INF, minnum = INF;
			for (int i = 1; i <= n; i++) {
				int p = min(k, a[i] / v);
				maxnum = max(maxnum, a[i] / p);
				minnum = min(minnum, a[i] / p);
			}
			ans = min(ans, maxnum - minnum);
		}
		cout << ans << endl;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值