A. Journey Planning

https://codeforces.com/contest/1320/problem/A

题意:给定n个数的数组a,现要构造数组,要求构造的数组所使用的a中元素的下标[ci, ci + 1, ...],c[i + 1] - c[i] = a[c[i + 1]] - a[c[i]],问所有符合条件的可构造出来的数组中,和最大是多少?

思路:c[i + 1] - c[i] = a[c[i + 1]] - a[c[i]],在物理上可解释为:经过一定长度的距离变化后,可以推测出变化的数值是多少;在数学上,也可以转化为:c[i + 1] - a[c[i + 1]] = c[i] - a[c[i]]。那么就直接红黑树一次遍历数组a即可。

总结:自己想只想到了暴力,看了solution的第一句话后恍然大悟,只要做一个公式变换就行。但是如果不是刻意往这个方面想的话,其实很难想到这种思路。 如果从物理意义上解释,我觉得更好理解一点。 构造出来的数组,c[i] 和 c[i + 1]的距离可能不是固定的,但是它们的变化比率是一定的,假如之前的下标变化长度为3,数值变化了6,那么下一个下标变化长度为5时,则数值变化应该为6 / 3 * 5 = 10。所以说,每个数跟它所在的位置有一个基数,这个基数是相等的。

顺便放一下耻辱的暴力解法:

inline void solve() {
	int n;
	cin >> n;

	vector<int> b(n);
	vector<int> dp(n, 0);
	for (int i = 0; i < n; ++i) {
		cin >> b[i];
		dp[i] = b[i];
	}

	for (int i = 0; i < n; ++i) {
		for (int j = i - 1; j >= 0; --j) {
			if (i - j == b[i] - b[j]) {
				dp[i] = max(dp[i], dp[j] + b[i]);
			}
		}
	}

	cout << *max_element(dp.begin(), dp.end()) << '\n';

}

正解:

inline void solve() {
    int n;
    cin >> n;

    map<int, long long> mapp;
    long long ans = 0;
    for (int i = 0; i < n; ++i) {
        int x;
        cin >> x;
        mapp[x - i] += x;
        ans = max(ans, mapp[x - i]);
    }

    cout << ans << '\n';
}
posted @ 2025-03-18 16:47  _Yxc  阅读(12)  评论(0)    收藏  举报