MT3032 环形喂猪

简介: MT3032 环形喂猪

93d3f654e08049a78126ee51bdd95a9f.jpg

792379819cc142c68a8ab20d005aa5ae.jpg

思路:

1.输出Error的情况:m>n/2

2.首先将饥饿值放到大根堆中,先喂最饿的猪i,则把i的饥饿值加到sum中;但也又可能喂i-1和i+1,所以此时需要反悔:把i取出来的同时,将a[i-1]+a[i+1]-a[i]放入堆中。(即保留取i,也保留取i-1和i+1的可能性),此时将i-1,i,i+1合并为一个节点

#include <bits/stdc++.h>
using namespace std;
const int N = 4e5 + 10;
int n, m, l[N], r[N], ans, a[N], tot;
bool mark[N];
struct node
{
    int id, v; // v为饥饿值
    bool operator<(const node &a) const
    { // 使用大根堆,重载<号
        return v < a.v;
    }
} tmp;
priority_queue<node> q; // 大根堆
int main()
{
    cin >> n >> m;
    if (m > n / 2)
    {
        cout << "Error!";
        return 0;
    }
 
    else
    {
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        for (int i = 2; i < n; i++)
        { // 处理链表
            l[i] = i - 1, r[i] = i + 1;
            q.push({i, a[i]});
        }
        // 处理环形(使用链表存储)
        l[1] = n, r[1] = 2;
        l[n] = n - 1, r[n] = 1;
        q.push({1, a[1]});
        q.push({n, a[n]});
        tot = n;
        for (int i = 1; i <= m; i++)
        {
            tmp = q.top(); // 取出堆头节点放入tmp中
            q.pop();
            if (mark[tmp.id])
            { // 如果已经被标记,即若取i,则标记i-1和i+1表示不能被取
                i--;
                continue;
            }
            ans += tmp.v; // 没被标记,则加到答案中
            // 新增节点
            a[++tot] = a[l[tmp.id]] + a[r[tmp.id]] - a[tmp.id];
            q.push({tot, a[tot]}); // 合并成一个节点
            // 更新链表中左右指针位置关系
            // 因为取了i就不能取i-1和i+1,所以位置关系类似
            //  i-2 tot i+2    tot为i-1 i i+1  tmp为i
            l[tot] = l[l[tmp.id]]; // tot左边为i-2,即tmp的l的l
            r[l[l[tmp.id]]] = tot; // i-2的右边为tot
            r[tot] = r[r[tmp.id]]; // tot右边为i+2,即tmp的r的r
            l[r[r[tmp.id]]] = tot; // i+2的左边为tot
            // 将这三个节点标记为已被处理
            mark[tmp.id] = mark[l[tmp.id]] = mark[r[tmp.id]] = 1;
        }
        cout << ans;
        return 0;
    }
}


相关文章
MT2041 三角形的个数
MT2041 三角形的个数
|
23天前
|
C++ iOS开发
|
23天前
|
人工智能 BI
MT3028 正反卡牌
MT3028 正反卡牌
|
25天前
牛客—CM11 链表分割
牛客—CM11 链表分割
【每日一题Day103】LC1669合并两个链表 | 模拟
思路:遍历链表找到list1中的第a−1个节点和第b+1个节点,然后将第a−1个节点指向list2链表的初始节点,list2链表的尾节点指向list1中的第b+1个节点
69 0
【每日一题Day103】LC1669合并两个链表 | 模拟