USACO月赛题解整理-集训Day2

1.★☆☆☆☆ 酸奶工厂

Yogurt factory, 2005 Mar
加上维护费用,计算出实际成本然后贪心。
本题要注意long long

const int maxn = 10010;
ll c[maxn], a[maxn], d, n;
int main()
{
    scanf("%lld%lld", &n, &d);
    rep(i, n) scanf("%lld%lld", &c[i], &a[i]);
    ll now = 10010, ans = 0;
    rep(i, n){
        now = min(now + d, c[i]);
        ans += now * a[i];
    }
    printf("%lld\n", ans);
    return 0;
}

2.★☆☆☆☆ 购买饲料

Buying Feed II, 2010 Jan

计算出加上油价后的实际价格,按照从小到大的顺序进行购买。

const int maxn = 10010;
struct node{
    int x, f, c, p;
    node(int _x = 0, int _f = 0, int _c = 0) : x(_x), f(_f), c(_c) {}
};
node a[maxn];
int cmp(node x, node y){
    return x.p < y.p;
}
int k, e, n;
int main()
{
    scanf("%d%d%d", &k, &e, &n);
    rep(i, n) {
        scanf("%d%d%d", &a[i].x, &a[i].f, &a[i].c);
        a[i].p = a[i].c + e - a[i].x;
    }
    sort(a, a + n, cmp);
    int ans = 0;
    rep(i, n){
        int cnt = min(k, a[i].f);
        k -= cnt;
        ans += a[i].p * cnt;
        if (k == 0) break;
    }
    printf("%d\n", ans);
    return 0;
}

3.★☆☆☆☆ 公司利润

Profits, 2011 Jan
经典的最大连续和问题,dp或者计算前缀和皆可

const int maxn = 100010;
int a[maxn], d[maxn];
int main()
{
    int n; scanf("%d", &n);
    rep1(i, n) scanf("%d", &a[i]);
    rep1(i, n) d[i] = d[i-1] > 0 ? d[i-1] + a[i] : a[i];
    int ans = -10000;
    rep1(i, n) ans = max(ans, d[i]);
    printf("%d\n", ans);
    return 0;
}

4.★★☆☆☆ 奶牛工资

Allowance, 2005 Oct
本题我只想到了每个月进行一次处理的办法,暂时没有批量计算的办法。
先把单张数额超过额定工资的部分发完。
然后进行”常规”工资发放。思路:在不浪费的情况下,尽量多花面额较大的币种。这样一遍花完可能就把工资发完了,如果没有发完,找面额最小的币种发一份即可。
但这么做的正确性存疑,我没有比较好的证明

const int maxn = 50;
struct money{
    ll v, k;
    money(ll _v = 0, ll _k = 0) : v(_v), k(_k){}
};
money a[maxn];
int n;
ll c;
int cmp(money x, money y){
    return x.v > y.v;
}
bool test(){
    ll now = c;
    rep(i, n) if (a[i].k){
        ll tmp = min(a[i].k, now / a[i].v);
        now -= tmp * a[i].v;
        a[i].k -= tmp;
    }
    if (now == 0) return true;
    for(int i = n-1; i >= 0; i--) if (a[i].k){
        a[i].k--;
        return true;
    }
    return false;
}
int main()
{
    scanf("%d%lld", &n, &c);
    rep(i, n) scanf("%lld%lld", &a[i].v, &a[i].k);
    sort(a, a + n, cmp);
    ll ans = 0;
    rep(i, n) if (a[i].v >= c){
        ans += a[i].k;
        a[i].k = 0;
    }
    while(test()) {
        ++ans;
        //rep(i, n) printf("%lld %lld\n", a[i].v, a[i].k);pn;
    }
    printf("%lld\n", ans);
    return 0;
}

5.★☆☆☆☆ 分期付款

Monthly Expense, 2007 Mar
一个普通的二分答案题,二分之后尽量还款

const int maxn = 100010;
ll n, m, a[maxn];
bool test(ll x){
    ll sum = 0, tot = 0;
    rep(i, n){
        if (a[i] > x) return 0;
        if (tot + a[i] <= x) tot += a[i];
        else {
            tot = a[i];
            sum++;
        }
    }
    sum++;
    return sum <= m;
}
int main()
{
    scanf("%lld%lld", &n, &m);
    rep(i, n) scanf("%lld", a + i);
    ll l = 0, r = 60000LL * 10000, mid, ans = r;
    while(r >= l){
        mid = (l+r) / 2;
        if (test(mid)){
            ans = mid;
            r = mid - 1;
        }else l = mid + 1;
    }
    printf("%lld\n", ans);
    return 0;
}

6.★★★☆☆ 整理绳子

Cow Laundry, 2003 Fall

建立相关映射之后直接求逆序数对,数据小暴力求逆序数对即可

const int maxn = 1010;
int a[maxn], b[maxn], ra[maxn], c[maxn], n; 
int main()
{
    scanf("%d", &n);
    rep(i, n) scanf("%d%d", &a[i], &b[i]);
    rep(i, n) ra[a[i]] = i;
    rep(i, n) c[i] = ra[b[i]];
    int ans = 0;
    rep(i, n) For(j, i+1, n-1) if (c[i] > c[j]) ++ans;
    printf("%d\n", ans);
    return 0;
}

你可能感兴趣的:(USACO月赛题解整理-集训Day2)