51nod 1494 選舉拉票 演算法設計策略

2022-02-27 09:02:20 字數 2778 閱讀 4195

codeforces基準時間限制:1 秒空間限制:131072 kb分值:80難度:5級演算法題

現在你要競選乙個縣的縣長。你去對每乙個選民進行了調查。你已經知道每乙個人要選的人是誰,以及要花多少錢才能讓這個人選你。現在你想要花最少的錢使得你當上縣長。你當選的條件是你的票數比任何乙個其它候選人的多(嚴格的多,不能和他們中最多的相等)。請計算一下最少要花多少錢。

input

單組測試資料。

第一行有乙個整數n (1 ≤ n ≤ 10^5),表示這個縣的選民數目。

接下來有n行,每一行有兩個整數ai 和 bi (0 ≤ ai ≤ 10^5; 0 ≤ bi ≤ 10^4),表示第i個選民選的是第ai號候選人,想要讓他選擇自己就要花bi的錢。

你是0號候選人(所以,如果乙個選民選你的話ai就是0,這個時候bi也肯定是0)。

output

輸出乙個整數表示花費的最少的錢。
input示例

5

1 21 2

1 22 1

0 0

output示例

3
analysis分析

正解:演算法設計策略 + 線段樹

為什麼特別標上這個演算法設計策略呢

這道題思路實在太複雜qwq

我們可以想象有多個河內塔,乙個塔就是乙個候選人,塔中一片就是乙個選民,候選人的「決心」越大片越大

因此我們這樣排序:每個候選人的選票小票在上大票在下(笑)

那麼我們怎麼搶票呢?

巨集觀策略是這樣的:搶票數最高的候選人最便宜的票

因此就是從每個塔的頂端拿選票堆在自己的塔上,直到自己的塔最高

所以這個東西想了我乙個下午+乙個晚上

所以我最後去看題解了(聽說ccz和sxt是第四個和第五個ac的orz)

題解的意思是這樣:從大到小列舉最終得票數, 然後根據每次的不同選擇計算出來的結果更新答案

那麼我列舉到自己有 i 張票的時候,需要保證其他候選人的票 < i

所以他們多出來的票我就都收了(當然收的是最便宜的,這裡用優先佇列維護)

砍完候選人的票之後,我的票可能仍然不夠 i 張,定義我之前搶過來的票數為 num ,

那麼從票倉裡再提取出 i - num + 投自己的最初的選票 張票即可

當然這裡是提取前 k 張最小的

這裡可以用權值線段樹維護

這樣,我們從大到小列舉,因此列舉到第 i-1 張時,可以直接繼承第 i 張的投票情況,無需初始化

詳情請看**

注意,票價是可以為 0 且不為自己選民的

code**

1 #include2 #include3 #include4 #include5

#define mid (l+r)/2

6#define lc (rt<<1)

7#define rc (rt<<1|1)

8#define maxn 200000

9using

namespace

std;

1011

long

long

n,list[maxn],qwq;

12bool

vis[maxn];

1314

struct

noddt[maxn*4

];17

18void modify(long

long rt,long

long l,long

long r,long

long pos,long

long

val)27}

2829

long

long query(long

long rt,long

long l,long

long r,long

long

pos)

3637 priority_queue

long,vector

long> ,greater

long> >heap[maxn];

3839

bool cmp1(long

long a,long

long b)

4041

intmain()

5152 sort(list+1,list+1+qwq,cmp1);

53//

cout << "list";

54//

for(int i = 1;i <= qwq;i++) printf("%d ",list[i]); cout << endl;

55long

long s = heap[0].size(),num = 0,sum = 0,ans =2e9;

5657

for(int i = n;i >= max(1ll,s);i--)

66 }ans = min(ans,sum+query(1,0,20000,i-(num+s)));

67//

printf("#%d: ans %d\n",i,ans);68}

6970 printf("

%lld

",ans);

7172

return0;

73 }

高效演算法設計策略

51Nod1494 選舉拉票

現在你要競選乙個縣的縣長。你去對每乙個選民進行了調查。你已經知道每乙個人要選的人是誰,以及要花多少錢才能讓這個人選你。現在你想要花最少的錢使得你當上縣長。你當選的條件是你的票數比任何乙個其它候選人的多 嚴格的多,不能和他們中最多的相等 請計算一下最少要花多少錢。input 單組測試資料。第一行有乙個...

51NOD1494 選舉拉票

現在你要競選乙個縣的縣長。你去對每乙個選民進行了調查。你已經知道每乙個人要選的人是誰,以及要花多少錢才能讓這個人選你。現在你想要花最少的錢使得你當上縣長。你當選的條件是你的票數比任何乙個其它候選人的多 嚴格的多,不能和他們中最多的相等 請計算一下最少要花多少錢。1 n 10 5,0 ai 10 5 ...

列舉 線段樹 51Nod1494 選舉拉票

直接做不太可做,我們可以列舉乙個 d 表示其他人最大值不大於 d時的情況。這樣就好做多了,比 d 大的部分就一定要全部扣掉。然後如果自己的票數不足 d,就需要在剩下的所有票裡取最便宜的前幾個,需要線段樹詢問前k小值的加和。從大到小列舉 d 即可。include include include def...