天天看點

Codeforces Round #536 (Div. 2) B. Lunar New Year and Food Ordering(思維)

題目連結:http://codeforces.com/contest/1106/problem/B

       題意是有n個菜,m個操作,接下來一行輸入每個菜的盤數,再下來一行輸入每盤菜的價格,接下來m行,每行兩個數分别表示第x個菜,要買y盤,輸出他要支付的價錢,如果第x個菜不夠y盤,他将會去買價格最低的菜,直到買夠y盤,如果所有的菜都賣完了也不夠y盤,他就會不高興,然後帶着那些不夠y盤的菜不給錢就走了。

       比較巧妙的思維題,寫法就是按題意分類讨論然後模拟就完了,暴力的去模拟的話,親測TLE,然後這裡需要一個巧妙的轉換,就是開一個id數組,将每盤菜的id按它的價格排序,然後用一個變量去記錄并更新最便宜的菜的位置就好了。說的不太清楚,看呆碼了解吧,不是很難。

AC代碼:

#include <bits/stdc++.h>
#define maxn 100005
#define ll long long
using namespace std;
int w[maxn], cnt[maxn], id[maxn];
int n,m;

bool cmp(int x,int y){
  return w[x] < w[y];
}

int main()
{
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++){
    scanf("%d",&cnt[i]);
    id[i] = i;
  }
  for(int i=1;i<=n;i++) scanf("%d",&w[i]);
  sort(id + 1, id + n + 1, cmp);       // 按價格排序
  int pos = 1;         // 标記最便宜的菜的位置
  while(m--){
    int x, y;
    scanf("%d%d",&x,&y);
    int p = min(cnt[x], y);            // 取二者最小值
    ll ans = (ll)p * (ll)w[x];
    cnt[x] -= p; y -= p;
    while(y && pos <= n){              // 如果y有剩餘,進入while循環
      if(cnt[id[pos]] == 0) pos++;     // 如果第pos便宜的菜賣完了 pos++
      p = min(cnt[id[pos]] , y);
      ans += (ll)p * (ll)w[id[pos]];
      cnt[id[pos]] -= p;
      y -= p;
    }
    if(y == 0) printf("%lld\n", ans);
    else puts("0");
  }
  return 0;
}           

複制