現要競選市長。有\(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 ...