求助……

  Catherine又跑上博客园来问题了……

7-9 策反加州

 

题目描述

来年一月份,特朗普将再次入主白宫,然而他却花了不少钱,这个时候,小 m 想知道,如果要让特朗普胜选,最少应该花多少钱。

因此,小 m 查询了美国选举制度,发现选举有以下几种形式:

一部分州在拿下一个州的一半及以上选民之后,即获得选票数要大于等于总票数的一半,就可以获得这个州的全部 张选举人票。

一部分州在则会按照比例分配,即会获得(选举人票数 自己获得的票数/该州所有选票数)下取整后的票数。

还有一部分州会采取如果选票超过或等于一半,即获得选票数要大于等于总票数的一半,则会获得固定的 张选举人票,其余还有 张选举人票按照比例分配,与第二种情况类似。

特朗普需要获得 的选票,或者获得或者超过 张选票,即可当选,而对于每个州而言,我们发现每多花 美元就可以使一个选民选择特朗普,请问,最小花费是多少,数据保证如果按照比例分配,则选民人数可以被选举人票数整除。

输入格式

第一行输入两个数个数 ,表示美国州的个数和获胜需要的选票数。

接下来 行,每行包含 个整数 ,分别表示按照一半以上分配的选举人票数,按照比例分配的选举人票数,选民总人数,在该州每收获一个选民需要的费用。显然,如果 ,则为第一种情况,如果 ,则为第二种情况,其余状况均为第三章情况。

输出格式

输出一行一个数,表示特朗普当选总统所需要的最小花费。

数据范围和约定

输入输出样例

输入样例 1

5 21
6 4 12 100 
3 2 9 100 
5 0 5 180 
0 6 10 150 
11 3 99 100

输出样例 1

2670

样例解释 1

总共有 40 张选票,我们先花 750 美元获得第 4 个州的全部选票 6 张,再花 600 美元获得第一个州 3 + 4 张选票,再花 720 美元获得第 3 个州的 4 张选票,最后耗费 600 美元获得第二个州的 2 + 2 张选票,共 21 张选票,花费 2570 元获得总统职位。

代码长度限制
16 KB
时间限制
1000 ms
内存限制
512 MB
栈限制
8192 KB
DeepSeek给的正解
#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
#include <climits>
using namespace std;

const long long INF = 1e18;

class SparseTable {
private:
    int n;
    vector<vector<long long>> st;
    vector<int> log_table;

public:
    SparseTable(const vector<long long>& arr) {
        n = arr.size();
        if (n == 0) return;

        int logn = 0;
        while ((1 << logn) < n) logn++;
        st.resize(logn + 1, vector<long long>(n));

        for (int i = 0; i < n; i++) {
            st[0][i] = arr[i];
        }

        for (int j = 1; j <= logn; j++) {
            int step = 1 << (j - 1);
            for (int i = 0; i + step < n; i++) {
                st[j][i] = min(st[j - 1][i], st[j - 1][i + step]);
            }
        }

        log_table.resize(n + 1);
        log_table[1] = 0;
        for (int i = 2; i <= n; i++) {
            log_table[i] = log_table[i / 2] + 1;
        }
    }

    long long query(int l, int r) {
        if (l > r) return INF;
        int len = r - l + 1;
        int j = log_table[len];
        return min(st[j][l], st[j][r - (1 << j) + 1]);
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    int t, w;
    cin >> t >> w;
    
    vector<long long> dp(w + 1, INF);
    dp[0] = 0;
    
    for (int idx = 0; idx < t; idx++) {
        int N, M, p, x;
        cin >> N >> M >> p >> x;
        int m = (p + 1) / 2;  
        if (N == 0) { 
            long long cost_full = 1LL * m * x;
            vector<long long> new_dp = dp;
            for (int j = 0; j <= w; j++) {
                if (dp[j] >= INF) continue;
                int new_j = min(w, j + M);
                new_dp[new_j] = min(new_dp[new_j], dp[j] + cost_full);
            }
            dp = new_dp;
        } else if (M == 0) { 
            int K = p / N;
            long long A = 1LL * K * x;
            deque<int> dq;
            vector<long long> new_dp(w + 1, INF);
            
            for (int j = 0; j <= w; j++) {
                while (!dq.empty() && dq.front() < j - N) {
                    dq.pop_front();
                }
                while (!dq.empty() && dp[dq.back()] - 1LL * dq.back() * A >= dp[j] - 1LL * j * A) {
                    dq.pop_back();
                }
                dq.push_back(j);
                long long min_val = dp[dq.front()] - 1LL * dq.front() * A;
                new_dp[j] = min_val + 1LL * j * A;
            }
            dp = new_dp;
        } else {  
            int K = p / N;
            long long A = 1LL * K * x;
            
            deque<int> dq1;
            vector<long long> new_dp1(w + 1, INF);
            for (int j = 0; j <= w; j++) {
                while (!dq1.empty() && dq1.front() < j - N) {
                    dq1.pop_front();
                }
                while (!dq1.empty() && dp[dq1.back()] - 1LL * dq1.back() * A >= dp[j] - 1LL * j * A) {
                    dq1.pop_back();
                }
                dq1.push_back(j);
                long long min_val = dp[dq1.front()] - 1LL * dq1.front() * A;
                new_dp1[j] = min_val + 1LL * j * A;
            }
            
            int g0 = (m + K - 1) / K;  
            int g_max_val = (m - 1) / K;  
            
            vector<long long> part1_arr(w + 1, INF);
            vector<long long> part2_arr(w + 1, INF);
            
            if (g0 <= N) {
                vector<long long> F(w + 1);
                for (int i = 0; i <= w; i++) {
                    F[i] = dp[i] - 1LL * i * A;
                }
                SparseTable st_F(F);
                
                for (int j = 0; j <= w; j++) {
                    int low = j - M - N;
                    int high = j - M - g0;
                    if (low < 0) low = 0;
                    if (high > w) high = w;
                    if (low > high) continue;
                    
                    long long min_F = st_F.query(low, high);
                    if (min_F >= INF) continue;
                    part1_arr[j] = min_F + 1LL * (j - M) * A;
                }
            }
            if (g_max_val >= 0) {
                SparseTable st_dp(dp);
                for (int j = 0; j <= w; j++) {
                    int low = j - M - g_max_val;
                    int high = j - M;
                    if (low < 0) low = 0;
                    if (high > w) high = w;
                    if (low > high) continue;
                    
                    long long min_dp_val = st_dp.query(low, high);
                    if (min_dp_val >= INF) continue;
                    part2_arr[j] = min_dp_val + 1LL * m * x;
                }
            }
            for (int j = 0; j <= w; j++) {
                long long best = min(new_dp1[j], min(part1_arr[j], part2_arr[j]));
                dp[j] = best;
            }
        }
    }
    
    cout << dp[w] << endl;
    return 0;
}
抄了一半想当鸽子
/*
mod 林钰翔 %%%
Catherine是HZOI鼎鼎大名的鸽子
*/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1e4 + 3;
const long double INF = 1e18;

ll f[maxn], g[maxn];

int main()
{
    int t, w; scanf("%d%d", &t, &w);
    for(int i=1; i<=w; i++) f[i] = INF;
    for(int i=1; i<=t; i++)
    {
        int N, M, p, x; scanf("%d%d%d%d", &N, &M, &p, &x);
        int m = (p + 1) / 2;//以此为界,I know
        if(N == 0)//要么买一半选票得到全部,要么放弃
        {
            ll c = m * x;
            memcpy(g, f, sizeof(f));//滚动数组
            //这个方程很好理解
            for(int j=0; j<=w; j++)
            {
                if(f[j] >= INF) continue;
                int p = min(w, j+M);
                g[p] = min(g[p], f[j]+c);
            }
            memcpy(f, g, sizeof(g));
        }
        else if(M == 0)//比例分配
        {
            int K = p / N;//比例系数,购买个数*K等于票数
            ll c = (ll)K * x;//买一张票的价格
            for(int o=0; o<=w; o++) g[o] = INF;
            deque<int> q;
            //我天……单调队列优化dp,这绝不是我能写得出来的
            for(int j=0; j<=w; j++)
            {
                //一个单调递增的队列,越往后越可能成为答案,值越小越可能成为答案
                while(!q.empty() && q.front()<j-N) q.pop_front();
                //上一个是从前找后,这个是从后找前
                //但是这个排除我看不懂……
                while(!q.empty() && f[q.back()]-(ll)q.back()*c>=f[j]-(ll)j*c) q.pop_back();
                q.push_back(j);
                ll val = f[q.front()]-(ll)q.front()*c;
                g[j] = val + (ll)j * c;
            }
            memcpy(f, g, sizeof(g));
        }
        else 
        {
            int K = p / N;
            ll c = (ll)K * x;
            for(int o=0; o<=w; o++) g[o] = INF;
            deque<int> q;
            for(int j=0; j<=w; j++)
            {
                while(!q.empty() && q.front()<j-N) q.pop_front();
                while(!q.empty() && f[q.back()]-(ll)q.back()*c>=f[j]-(ll)j*c) q.pop_back();
                q.push_back(j);
                ll val = f[q.front()]-(ll)q.front()*c;
                g[j] = val + (ll)j * c;
            }
            //以上是比例部分
            //后面又是什么……无法理解!简直是无法理解!……鸽了吧孩子
        }
    }
    
    return 0;
}
posted @ 2025-07-09 14:26  Catherine_leah  阅读(61)  评论(4)    收藏  举报
/* */