只是11分,思路错了吗
  • 板块P11396 排队
  • 楼主tsttkx
  • 当前回复1
  • 已保存回复1
  • 发布时间2024/12/14 23:38
  • 上次更新2024/12/14 23:45:57
查看原帖
只是11分,思路错了吗
1587336
tsttkx楼主2024/12/14 23:38

思路是 :因为选组是连续的元素,所以分组应该是一个元素的左右位置的。又因为是字典序最大的,所以 例如 8 1 9 ,1该选9,而不是8,1 、9都标记上被选择。下一次就是 2挑选周围的元素。

记录所有元素的位置(所有元素是不重复的,1-n的一个排列),然后从 1 开始遍历,查询1位置左右的哪个数大,直接输出放置并且vis标记1 和 1两边的数据。

贡献自己想出的样例

9
1 9 8 3 7 6 5 4 2

1 9 2 4 3 8 5 6 7 
6
6 5 4 1 2 3

1 4 2 3 5 6 
15
15 13 12 8 9 1 10 3 7 4 2 5 11 14 6

1 10 2 5 3 7 4 6 14 8 12 9 11 13 15 
10
1 10 4 7 3 2 9 5 6 8

1 10 2 9 3 7 4 5 6 8 

下面是鄙人的垃圾代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pp;
const int N = 300015;
int a[N];
int cnt[N];  // 记录每个 数的  位置
int vis[N];  // 标记是否被使用
int n;

int checkRight(int i) {
    if ((cnt[i] - 1 < 1 || vis[a[cnt[i] - 1]]) && cnt[i] + 1 <= n && !vis[a[cnt[i] + 1]])
        return true;
    if (cnt[i] + 1 <= n && a[cnt[i] + 1] - i > 1 && a[cnt[i] + 1] > a[cnt[i] - 1] && !vis[a[cnt[i] + 1]])
        return true;

    return false;
}

int checkLeft(int i) {
    if ((cnt[i] + 1 > n || vis[a[cnt[i] + 1]]) && cnt[i] - 1 >= 1 && !vis[a[cnt[i] - 1]])
        return true;
    if (cnt[i] - 1 >= 1 && a[cnt[i] - 1] - i > 1 && a[cnt[i] - 1] > a[cnt[i] + 1] && !vis[a[cnt[i] - 1]])
        return true;

    return false;
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        cnt[a[i]] = i;
    }

    for (int i = 1; i <= n; i++) {
        // cnt[i] 是i位置
        if (vis[i]) {
            continue;
        }
        if (checkLeft(i)) {
            cout << i << ' ' << a[cnt[i] - 1] << ' ';
            vis[i] = vis[a[cnt[i] - 1]] = 1;
        } else if (checkRight(i)) {
            cout << i << ' ' << a[cnt[i] + 1] << ' ';
            vis[i] = vis[a[cnt[i] + 1]] = 1;
        } else {
            cout << i << ' ';
            vis[i] = 1;
        }
    }
    return 0;
}
2024/12/14 23:38
加载中...