- CSP-J 2021 T4 小熊的果篮
小熊的果篮
- @ 2025-8-16 15:23:29
双向循环链表模拟:
1.用一个双链表维护块内水果的编号关系。
2.用一个双链表维护块与块之间的水果关系,块的地址用块内最后一个水果编号。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int l[N], r[N], bl[N], br[N]; // l,r是块内双链表,bl, br块之间双链表
int w[N];
int main()
{
freopen("bear.in", "r", stdin);
freopen("bear.out", "w", stdout);
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> w[i];
int cnt = 0; // 块的数量
for (int i = 1, last = n; i <= n; i++)
{
int j = i + 1;
while (j <= n && w[i] == w[j]) j++; // i~j-1连续的一段
// 建立i~j-1之间块内双向链表
for (int k = i; k < j; k++) l[k] = k-1, r[k] = k+1;
l[i] = j-1;
r[j-1] = i;
// 建立块与块之间的关系,last代表上一个块的地址,当前块地址为j-1
br[last] = j-1, bl[j-1] = last;
last = j-1;
i = j-1;
cnt ++;
}
int head = br[n]; // 最后一个块的右边就是第一个块的末尾编号
while (true)
{
int new_head = -1;
for (int t = cnt, i = head; t != 0; t--, i = br[i])
{
int k = r[i];
cout << k << " ";
if (i == k) // 块内只有一个水果
{
br[bl[k]] = br[k], bl[br[k]] = bl[k]; // 整块删除
cnt --;
}
else // 块内多个水果
{
r[l[k]] = r[k], l[r[k]] = l[k]; // 删除取走的水果
if (new_head == -1) new_head = i;
}
}
if (cnt == 0) break;
head = new_head;
if (cnt > 1) // 可能需要合并,处理合并逻辑
{
new_head = -1;
for (int t = cnt, i = head; t > 1; t --, i = br[i])
{
int j = br[i]; // i是当前块,j是下一个块
if (w[i] == w[j]) // 水果种类相同
{
// 合并两个相邻块
int ri = r[i], rj = r[j];
r[i] = rj, l[rj] = i;
l[ri] = j, r[j] = ri;
// 将 i 连到 j,删除i
bl[br[i]] = bl[i], br[bl[i]] = br[i];
cnt --;
}
else if (new_head == -1) new_head = i;
}
if (new_head == -1) new_head = bl[head];
head = new_head;
}
cout << endl;
}
return 0;
}
0 条评论
目前还没有评论...
信息
- ID
- 342
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 9
- 已通过
- 6
- 上传者