51Nod 1494 選舉拉票 權值線段樹

2022-06-12 21:27:08 字數 1322 閱讀 5559

現要競選市長。有\(n\)個選民投票。

每行兩個數字\(a_i,b_i\)表示第\(i\)個選民投給\(a_i\)號候選人,必須花費\(b_i\)使他投你的票。

你是第0號候選人。

問最少花多少錢使你競選成功。

\[1\leq n \leq 10^5\\

0\leq a_i \leq 10^5,0\leq b_i \leq 10^4

\]從\(n - st到max(1,st)\)列舉要收買多少人。

假設對每個候選人票數小於\(i\)要收買\(num\)個人。那麼還需要\(i - num\)個人。

顯然我們貪心的選擇剩下的人。

為了快速計算這些人的總和,可以建立一顆權值線段樹,做到單次查詢\(o(logn)\)

權值線段樹的節點下標(不是真正的下標)表示權值,num表示個數,sum表示總和(方便詢問)

還要注意這裡如果size小於i就直接break,大大減少了迴圈次數。這也是之前排序的原因。

priority_queue, greater> q[maxn];

vectorid;

int vis[maxn];

int cnt;

int st;

bool cmp(int x, int y)

struct node ;

node node[maxn << 2];

void push_up(int i)

void update(int i, int l,int r,int p, ll v)

int mid = l + r >> 1;

if (p <= mid) update(i << 1, l, mid, p, v);

else update(i << 1 | 1, mid + 1, r, p, v);

push_up(i);

}int query(int i, int l, int r, int k)

int main()

q[x].push(y);

update(1, 0, 10000, y, 1);

if (!vis[x])

}sort(id.begin(), id.end(),cmp);

int ans = inf;

int res = 0, num = 0;

int mx = max(1, st);

for (re int i = n; i >= mx; i--)

}ans = min(ans, res + query(1, 0, 10000, i - num - st));

}put(ans);

}

51Nod1494 選舉拉票

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

51NOD1494 選舉拉票

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

51Nod 1494 選舉拉票(權值線段樹)

一開始有start個人投自己,num表示當前已經收買了多少人,從大到小列舉自己以i張票當選,那麼其他人的票數一定要小於i,拿錢收買他們花費最少的 i的這部分人,再加上另外要收買的i start num個最便宜收買的花費就是當前答案,這裡可以對每個人的收買代價建立權值線段樹來查詢收買前i start ...