P3102取數nkoj 堆的應用

2021-08-07 08:11:14 字數 1353 閱讀 4665

問題描述

n個整數組成的乙個環,現在要從中取出m個數,取走乙個數字就不能取跟它相鄰的數字(相鄰的數不能同時取)。要求取出的數字的總和盡可能大,問這個最大和是多少? 如果無解,請輸出「error!」

輸入格式

第一行包含兩個正整數n、m。

第二行為n個整數ai。

輸出格式

僅乙個整數,表示所求結果。如果無解輸出「error!」,不包含引號。

樣例輸入

8 4

8 5 6 2 3 4 8 9

樣例輸出

我們先把每個數字以及它的編號拿入堆中。建大根堆。並記錄下每個數左右元素的編號。l[k],r[k]。

最後要輸出的答案是ans。初始化為0。

然後每次從堆裡面拿出堆頂元素,ans+這個堆定元素的值。

假設我們當前取出的堆頂元素的編號為k。我們現在新生成乙個數p[i]=p[l[k]]+p[r[k]]-p[k]。

編號為i的數左邊的數的編號我們賦為l[l[k]]。右邊的數賦為r[r[k]]。

然後r[r[k]]的左邊是i。l[l[k]]右邊是i。( 類似於鍊錶的操作)

ps:注意陣列範圍

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define maxn 200005

struct node;

bool

operator

<(node a,node b);

for(i=1;i<=n;i++)

l[1]=n;r[1]=2;temp.a=a[1];temp.x=1;q.push(temp);

l[n]=n-1;r[n]=1;temp.a=a[n];temp.x=n;q.push(temp);

for(i=2;i1;r[i]=i+1;temp.a=a[i];temp.x=i;

q.push(temp);

}tot=n;

for(i=1;i<=m;i++)

ans+=tmp.a;tot++;

a[tot]=a[l[tp]]+a[r[tp]]-a[tp];

mark[l[tp]]=mark[r[tp]]=mark[tp]=true;

r[l[l[tp]]]=l[r[r[tp]]]=tot;

l[tot]=l[l[tp]];r[tot]=r[r[tp]];

temp.a=a[tot]; temp.x=tot;

q.push(temp);

}cout

<}

題 貪心 神似DP NKOJ3102 取數

nkoj3102 取數 時間限制 20000 ms 空間限制 165536 kb 問題描述 n個整數組成的乙個環,現在要從中取出m個數,取走乙個數字就不能取跟它相鄰的數字 相鄰的數不能同時取 要求取出的數字的總和盡可能大,問這個最大和是多少?如果無解,請輸出 error 輸入格式 第一行包含兩個正整...

洛谷P1392 取數 堆

題目傳送門 在乙個n行m列的數陣中,你須在每一行取乙個數 共n個數 並將它們相加得到乙個和。對於給定的數陣,請你輸出和前k小的取數方法。輸入格式 第一行,三個數n,m,k。第2 n 1行,每行m個正整數 輸出格式 一行共k個數,代表在每一行取乙個數前k小的加和 輸入樣例 1 複製 3 3 2 1 2...

P1005 矩陣取數

看完題可能第一時間並沒有清晰的思路。讓我們一步一步的來考慮這道題目。題目中描述操作為每次從所有的行中選取,這樣做有些麻煩。仔細思考一下可以發現行與行之間互不干涉,所以我們可以對每行操作到底,最後統計答案。每行怎麼選取當然難不倒聰明的oier了,設f i j 表示某行從第i位到第j位的最優答案。轉移如...