单链表篇 + 双链表 模板 + 例题

单链表 —— 模板题 AcWing 826. 单链表
// head存储链表头,e[]存储节点的值,ne[]存储节点的next指针,idx表示当前用到了哪个节点
int head, e[N], ne[N], idx;

// 初始化
void init()
{
head = -1;
idx = 0;
}

// 在链表头插入一个数a
void insert(int a)
{
e[idx] = a, ne[idx] = head, head = idx ++ ;
}

// 将头结点删除,需要保证头结点存在
void remove()
{
head = ne[head];
}

双链表 —— 模板题 AcWing 827. 双链表
// e[]表示节点的值,l[]表示节点的左指针,r[]表示节点的右指针,idx表示当前用到了哪个节点
int e[N], l[N], r[N], idx;

// 初始化
void init()
{
//0是左端点,1是右端点
r[0] = 1, l[1] = 0;
idx = 2;
}

// 在节点a的右边插入一个数x
void insert(int a, int x)
{
e[idx] = x;
l[idx] = a, r[idx] = r[a];
l[r[a]] = idx, r[a] = idx ++ ;
}

// 删除节点a
void remove(int a)
{
l[r[a]] = l[a];
r[l[a]] = r[a];
}
栈 —— 模板题 AcWing 828. 模拟栈
// tt表示栈顶
int stk[N], tt = 0;

// 向栈顶插入一个数
stk[ ++ tt] = x;

// 从栈顶弹出一个数
tt -- ;

// 栈顶的值
stk[tt];

// 判断栈是否为空,如果 tt > 0,则表示不为空
if (tt > 0)
{

}

给定一个长度为 N 的整数数列:A1, A2, ... , AN。你要重复以下操作 K 次:
每次选择数列中最小的整数(如果最小值不止一个,选择最靠前的),将其删除。
并把与它相邻的整数加上被删除的数值。
输出 K 次操作后的序列。

输入格式

第一行包含两个整数 N 和 K。
第二行包含 N 个整数,A1, A2, ... , AN。
对于 20% 的数据,1 ≤ K < N ≤ 10000。
对于 100% 的数据,1 ≤ K < N ≤ 5 × 1e5,0 ≤ Ai ≤ 1e8。

输出格式

输出 N − K 个整数,中间用一个空格隔开,代表 K 次操作后的序列。

include <bits/stdc++.h>

define ios ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)

define int long long

using namespace std;
const int N = 1e6 + 10;
typedef pair<int, int> pii;

int e[N], l[N], r[N], idx;
int cur[N]; // 记录节点的当前值
bool st[N]; // 标记是否被删除
priority_queue<pii, vector, greater> que;
vector res;

void init() {
r[0] = 1; l[1] = 0;
idx = 2;
}

void insert(int a, int x) {
e[idx] = x;
l[idx] = a; r[idx] = r[a];
l[r[a]] = idx; r[a] = idx;
cur[idx] = x; // 初始化cur
idx++;
}

void remove(int a) {
l[r[a]] = l[a];
r[l[a]] = r[a];
st[a] = true;
}

signed main() {
ios;
cin >> n >> k;
init();

for (int i = 1; i <= n; i++) {
    int x;
    cin >> x;
    insert(l[1], x); // 在尾节点前插入
    que.push({x, idx - 1}); // 插入的是新节点,索引为idx-1
}

int cnt = 0;
while (cnt < k) {
    auto f = que.top();
    que.pop();
    int ver = f.second, val = f.first;

    // 检查是否为最新值或已删除
    if (st[ver] || cur[ver] != val) continue;

    // 处理左右邻居
    int left = l[ver], right = r[ver];
    if (left != 0 && !st[left]) {
        e[left] += val;
        cur[left] = e[left]; // 更新cur
        que.push({cur[left], left});
    }
    if (right != 1 && !st[right]) {
        e[right] += val;
        cur[right] = e[right]; // 更新cur
        que.push({cur[right], right});
    }

    remove(ver);
    cnt++;
}

// 收集结果
for (int i = r[0]; i != 1; i = r[i]) {
    if (!st[i]) res.push_back(e[i]);
}

// 输出
for (int i = 0; i < res.size(); i++) {
    if (i > 0) cout << " ";
    cout << res[i];
}
cout << endl;

return 0;

}

posted on 2025-04-10 20:56  下头小美  阅读(15)  评论(0)    收藏  举报