2024牛客暑期多校训练营7 C Array Sorting 题解

乱搞

非正解写法。分类讨论各种情况。

  • 降序排序

对应交换即可

  • 数组个数小

直接考虑相邻的交换

  • 其他都看做随机数据

考虑结合前面情况,很容易想到,先把数组变成一个尽量有序的数组(每个元素和自己正确的位置相差不大)。最后再多次相邻交换,使得每个元素都在正确位置。

把数组变成一个尽量有序的过程,很容易想到希尔排序。我们做一个类似希尔排序的操作,每次设定\(d\),使\(i\)\(i+d\)交换,然后\(d/=2\)。多次进行这样的操作,但是发现每次都有些位置\(j\)一直是和\(j-d\)交换的,在这些位置不少于某个值的时候,我们考虑让\(j\)\(j+d\)交换,这样我们就得到了个尽量有序的数组。

很好的过样例,submit WA。剩下的就是调参的内容了。写一份check代码。打印每次选择的有序对时,成功交换的比例,调参使得前几次交换比例高,后面交互比例为0。你问我正确性?我也不知道,我只能说本地随机一百组数据都是可以通过的。

细节:
  • 特判\(n=0,1\)
  • 注意每个有序对\((x,y)\)\(x\)都小于\(y\)
  • 一个位置一次交换只能出现一次
  • \(d\)的选择不能每次都是\(n\)的因数,不然有些值一直在某些固定位置选择,并且不动。
vector<pii>ans[205];
bool vis[MAXN];
void solve() {
    n = read();
    if (n == 1) return printf("0\n"), void();
    if (n == 2) return printf("1\n1 0 1\n"), void();
    for (int i = 0, j = n - 1; i < j; ++i, --j)
        ans[1].push_back({i, j});
    m = 2;
    if (n <= 10) {
        for (; m <= 200; ++m) {
            for (int i = 1 - (m & 1); i + 1 < n; i += 2) {
                int x = i, y = i + 1;
                if (x > y)swap(x, y);
                ans[m].push_back({x, y});
            }
        }
    } else {
        for (int k = 0; k < 24; ++k) {
            for (int len = 10000 >> (k + 1); len >= 5; len >>= 1) {
                if (len > n / 2)continue;
                memset(vis, 0, sizeof(vis));
                for (int i = 0; i + len < n; ++i) {
                    int x = i, y = i + len;
                    if (x > y)swap(x, y);
                    if (!vis[x] && !vis[y]) {
                        vis[x] = vis[y] = 1;
                        ans[m].push_back({x, y});
                    }
                }
                ++m;
                if (len >= n / 10)continue;
                memset(vis, 0, sizeof(vis));
                for (int i = len; i + len < n; ++i) {
                    int x = i, y = i + len;
                    if (x > y)swap(x, y);
                    if (!vis[x] && !vis[y]) {
                        vis[x] = vis[y] = 1;
                        ans[m].push_back({x, y});
                    }
                }
                ++m;
            }
        }
        for (; m <= 200; ++m) {
            for (int i = 1 - (m & 1); i + 1 < n; i += 2) {
                int x = i, y = i + 1;
                if (x > y)swap(x, y);
                ans[m].push_back({x, y});
            }
        }
    }
    printf("%d\n", m - 1);
    for (int i = 1; i < m; ++i, enl) {
        printf("%d ", ans[i].size());
        for (auto& [x, y] : ans[i])printf("%d %d ", x, y);
    }
}

posted on 2024-08-06 23:36  Quixotica  阅读(27)  评论(0编辑  收藏  举报