LibreOJ 6254 最優卡組 堆

2021-09-25 22:44:09 字數 2212 閱讀 7937

有n

nn個卡包,第i

ii個卡包裡有c

ic_i

ci​張卡,每張卡有乙個能力值。現在從每個卡包裡面選一張卡,定義一種方案的價值為選的卡的能力值之和,求價值前k

kk大的方案。

n ,k

,∑ci

≤300000

n,k,\sum c_i\le300000

n,k,∑c

i​≤3

0000

0 很自然的想法是用乙個堆來維護所有狀態的價值,從價值最大的狀態開始,每次往後拓展一些狀態,關鍵在於如何設定狀態。

先把所有卡組的卡按能力值從大到小排序。設(va

l,x,

y,z)

(val,x,y,z)

(val,x

,y,z

)為乙個狀態,其中val

valva

l表示狀態的價值,處理了前x

xx個卡組,第x

xx個卡組選的是第y

yy張卡,z表示當前狀態是否由2或3操作轉移而來,且編號大於x

xx的卡組選的均為第一張卡。

然後有如下轉移:

1、若y

yy​,也就是第x

xx個卡組還能繼續拓展,則轉移到(va

l+..

.,x,

y+1,

0)

(val+...,x,y+1,0)

(val+.

..,x

,y+1

,0)2、若y

y<

n,也就是還能拓展到下乙個卡包,則讓下乙個卡包選擇第二章卡,也就是轉移到(va

l+..

.,x+

1,2,

1)

(val+...,x+1,2,1)

(val+.

..,x

+1,2

,1)3、若x

x=1

z=1z=

1,也就是當前卡組選的是第二張卡,且還能拓展到下乙個卡包,則撤銷掉當前卡組的第二張卡,並選擇下乙個卡組的第二張卡,也就是轉移到(va

l+..

.,x+

1,2,

1)

(val+...,x+1,2,1)

(val+.

..,x

+1,2

,1)可以發現這樣可以不重不漏地構造出所有方案,而如果我們把卡組按照最大值

−次大值

最大值-次大值

最大值−次大

值從小到大排序,就可以保證每次被轉移到狀態的價值必然會小於當前狀態的價值,那麼就可以按照價值從大到小地列舉方案了。

#include

#include

#include

#include

#include

#include

#include

#define pb push_back

typedef

long

long ll;

const

int n=

300005

;int k,n,id[n]

;std:

:vector<

int> vec[n]

;struct data};

std:

:priority_queue que;

bool cmp

(int x,

int y)

bool cmp

(int x,

int y)

intmain()

} n=tmp;

for(

int i=

1;i<=n;i++

) id[i]

=i; std:

:sort

(id+

1,id+n+

1,cmp)

;for

(int i=

1;i<=n;i++

) sum+

=vec[i][0

];que.

push

((data));

while

(k--))

;if(xpush

((data));

if(x1) que.

push

((data));

}return0;

}

與眾不同 LibreOJ 10121

題目描述 a 是某公司的 ceo,每個月都會有員工把公司的盈利資料送給 a,a 是個與眾不同的怪人,a 不注重盈利還是虧本,而是喜歡研究 完美序列 一段連續的序列滿足序列中的數互不相同。a 想知道區間 l,r l,r 之間最長的完美序列長度。輸入格式 第一行兩個整數 n,m n,m,n n 表示連續...

題解 LibreOJ 6229 題解

題目鏈結 給定 n 求 f n sum n sum i frac i,j bmod 10 9 7 1 le n le 10 9 首先,這個求和範圍有些不爽,利用對稱性轉化一下得 f n frac 12 left n sum n sum n frac i,j right 然後推一下式子 begin s...

LibreOJ 6053 簡單的函式

某一天,你發現了乙個神奇的函式f x f x 它滿足很多神奇的性質 1.f 1 1 f 1 12.f pc p c f p c p c 表示異或 3.f a b f a f b f a b f a f b a a 與b role presentation b b互質 你看到這個函式之後十分高興,於是...