題目大意:
解題思路:
根據題意得:當時是固定點
我們設翻轉區間爲,如果不滿足翻轉後都成爲固定點那麼我們將區間縮小爲一定是更優的
且當時翻轉後都爲固定點
然後我們將存入中意思是以爲翻轉點時這個點可能會成爲固定點(還要考慮翻轉區間)
我們按照每個點成爲固定點需要翻轉的區間排序(從小到大)
枚舉每個點然後更新答案就可以了
#include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm>
#define pb push_back
using namespace std;
int n, ans, mid;
int a[100005], sum[100005];
vector <int> v[200005];
bool cmp(int x, int y) {
return abs(x*2 - mid) < abs(y*2 - mid);
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
v[a[i]+i].pb(i);
sum[i] = sum[i-1] + (a[i] == i); //處理前綴和求出除翻轉區間外本來有的固定點
}
int N = n << 1;
for (int i = 2; i <= N; ++i) { //枚舉翻轉點
mid = i;
int num = v[i].size();
sort(v[i].begin(), v[i].end(), cmp); //排序
for (int j = 0; j < num; ++j) {
int l = v[i][j], r = i - v[i][j]; //翻轉區間
if (l > r) swap(l, r);
ans = max(ans, sum[l-1] + sum[n] - sum[r] + j+1); //更新答案
//j+1是因爲我們按照區間大小排序所以當前枚舉區間是包括之前區間的要把之前的點算上
}
}
printf("%d", ans);
}