JZOJ6288 [] []グループNOIPは、回転子セグメントを改善します

効果の対象に

与えます\(N-に\)する場合、配置された\([I] =私は \)は、その後、\(私は\)今、あなたはそれが最大反転固定小数点を求めた後、範囲のフリップを選択することができ、固定点であります(のみ可能一度裏返し、間隔を選択してください)。

分析

最初の交換のために\((i、j)は\ ) のみの3つの状況があります。

  • \(私は\)交換をリセットした後、その上方位置にありません。(\ (J \)共感)
  • \(私は\)交換がまだされた後、彼の場所ではありません。
  • \(私は\)なくなっ交換した後、彼の場所になりました。

ライン上のプレフィックスと統計と後者の二つは、最初のものは、我々は見つける\((I、[I ])\) の中央に\((I、[I ])\) 中央にぶら下がっその後、長さでソートし、我々は唯一の要素を扱うには、他の取引所は、プレフィックスと統計を使用することができるようになります交換を、リセットしています。

コード

ビット醜いコードは、私を許して。

#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100007;

int n, ret = -0x3f3f3f3f, sum[N], a[N];

struct note { int l, r, len; };
vector<note> lis1[N], lis2[N];

int cmp(note a, note b) { return a.len < b.len; }

void doit1()
{
    for (int i = 1, p, q; i <= n; i++)
    {
        p = i, q = a[i];
        if (p > q) swap(p, q);
        if ((q - p) % 2 == 0) lis1[(p + q) / 2].push_back((note){p, q, q - p + 1});
    }
    for (int i = 1; i <= n; i++)
    {
        sort(lis1[i].begin(), lis1[i].end(), cmp);
        int sz = lis1[i].size(), s = 0;
        for (int j = 0, lasl = i, lasr = i; j < sz; j++)
        {
            if (lis1[i][j].len == 1) { ret = max(ret, s); continue; }
            if (lis1[i][j].l < lasl) s -= sum[lasl - 1] - sum[lis1[i][j].l];
            if (lasr < lis1[i][j].r) s -= sum[lis1[i][j].r - 1] - sum[lasr];
            if (j < sz - 1)
            {
                if (lis1[i][j].len == lis1[i][j + 1].len) s += 2, ++j;
                else s += 1;
            }
            else s += 1;
            lasl = lis1[i][j].l, lasr = lis1[i][j].r;
            ret = max(ret, s);
        }
    }
}

void doit2()
{
    for (int i = 1, p, q; i <= n; i++)
    {
        p = i, q = a[i];
        if (p > q) swap(p, q);
        if ((q - p) % 2 == 1) lis2[(p + q) / 2].push_back((note){p, q, q - p + 1});
    }
    for (int i = 1; i <= n; i++)
    {
        sort(lis2[i].begin(), lis2[i].end(), cmp);
        int sz = lis2[i].size(), s = 0;
        for (int j = 0, lasl = i + 1, lasr = i; j < sz; j++)
        {
            if (lis2[i][j].l < lasl) s -= sum[lasl - 1] - sum[lis2[i][j].l];
            if (lasr < lis2[i][j].r) s -= sum[lis2[i][j].r - 1] - sum[lasr];
            if (j < sz - 1)
            {
                if (lis2[i][j].len == lis2[i][j + 1].len) s += 2, ++j;
                else s += 1;
            }
            else s += 1;
            lasl = lis2[i][j].l, lasr = lis2[i][j].r;
            ret = max(ret, s);
        }
    }
}

int main()
{
    //freopen("rotate.in", "r", stdin);
    //freopen("rotate.out", "w", stdout);
    //freopen("in", "r", stdin);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]), sum[i] = sum[i - 1] + (i == a[i]);
    doit1();
    doit2();
    printf("%d\n", sum[n] + ret);
    return 0;
}

おすすめ

転載: www.cnblogs.com/zjlcnblogs/p/11328305.html