第一眼看上去让人以为是数位 DP,但看一眼样例 2 就知道直接枚举就行了。
六层循环暴力枚举。
复杂度 \(O(10^6)\)。
有思维含量的一题。
我们横纵坐标分开考虑,对于每一个矩形,每次操作会使其内部元素的横坐标上下对调。
纵坐标也同理,左右对调。
而这种反转操作我们显然可以直接用两棵文艺平衡树维护,复杂度 \(O(n\log n)\)。
标程的做法更巧妙一下。我们可以把一条链收尾相接,两段序列的反转就相当于圆的反转。
所以我们可以只定位其中两个点,然后根据其最终位置填补出剩下元素。复杂度 \(O(n)\)。
[ARC153C] ± Increasing Sequence
调整调整调整!
令 \(x=[1,2,3...n]\),则 \(sum=\sum\limits_{i=1}^{n}x_i\cdot a_i\)。
调整的方法有两种,\(x\) 前缀 \(-1\),\(x\) 后缀 \(+1\)。
然后我们发现,如果 \(x\) 存在正前缀和,则必然存在和为 \(1\) 的前缀;如果 \(x\) 存在负前缀和,则必然存在和为 \(-1\) 的前缀。后缀同理。
所以直接根据 \(sum\) 的正负,找前缀 \(1\),前缀 \(-1\),后缀 \(1\),后缀 \(-1\) 进行相应的调整即可。
复杂度 \(O(n)\)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
ll n, a[N], ans[N], sum[N], s = 0;
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= n; ++i) ans[i] = i;
for (int i = 1; i <= n; ++i) s += a[i] * i, sum[i] = sum[i - 1] + a[i];
int p1 = -1, p2 = -1, p3 = -1, p4 = -1;
for (int i = 1; i <= n; ++i) {
if (sum[i] == -1) p1 = i;
if (sum[i] == 1) p2 = i;
if (s - sum[i - 1] == -1) p3 = i;
if (s - sum[i - 1] == 1) p4 = i;
}
if (s > 0) {
if (p3 != -1) for (int i = p3; i <= n; ++i) ans[i] += s;
else if (p2 != -1) for (int i = 1; i <= p2; ++i) ans[i] -= s;
} else {
if (p4 != -1) for (int i = p4; i <= n; ++i) ans[i] -= s;
else if (p1 != -1) for (int i = 1; i <= p1; ++i) ans[i] += s;
}
ll tmp = 0;
for (int i = 1; i <= n; ++i) tmp += ans[i] * a[i];
if (tmp == 0) {
cout << "Yes" << endl;
for (int i = 1; i <= n; ++i) cout << ans[i] << " ";
cout << endl;
} else cout << "No" << endl;
return 0;
}
标签:前缀,int,sum,后缀,ARC153,复杂度,调整
From: https://www.cnblogs.com/HQJ2007/p/17561574.html