B. Lunar New Year and Food Ordering
题意:
第一行输入n,m。餐馆一共有n种菜,会有m个顾客前来点菜。
第二行是每种菜的数量,第三行是每种菜(一道菜)的成本。
从第四行开始有m行,每一行输入两个数(x y) 分别表示第几道菜 和 需要几道这样的菜。如果顾客所点的这道菜没有那么多,就从所有菜中价格最便宜的补(补的菜的价格是菜原来的价格),如果有多种价格相同最便宜的菜,就先从先出现的菜拿。 一个顾客如果不能够拿到y道菜,他就会生气的离开,它的成本就为0。
输出每一位顾客所需的成本。
一直没想清楚怎样将排好序的菜的位置 与 输入的原菜的位置相联系,看了大佬的代码发现只需要一个存储位置的数组就可以。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
ll num[maxn],v[maxn];
int indx[maxn];
int cmp(int x,int y)
{
if(v[x]==v[y])
return x<y;
return v[x]<v[y];
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%I64d",num+i);
for(int i=1;i<=n;i++)
scanf("%I64d",v+i);
for(int i=1;i<=n;i++)
indx[i] = i;
sort(indx+1,indx+n+1,cmp);
int x,y;
int k = 1;
while(m--)
{
scanf("%d%d",&x,&y);
if(num[x]>=y) //第一种情况
{
num[x] -= y;
printf("%I64d\n",v[x]*y);
}
else //第二种情况
{
ll sum = num[x]*v[x];
y -= num[x];
num[x] = 0;
int flag = 0; //判断顾客是否会生气离开
for(;k<=n;k++) //每次从1开始遍历会超时
{
if(num[indx[k]]<y)
{
sum += num[indx[k]]*v[indx[k]];
y -= num[indx[k]];
num[indx[k]] = 0;
}
else
{
sum += v[indx[k]]*y;
num[indx[k]] -= y;
break; // 直接跳出循环且所对应的数量已经减少,当为后来的顾客补菜时还是从 indx[k] 开始
}
if(k==n) // 如果顾客已经得到y道菜就会在上一步跳出循环,所以当条件成立时,就表示顾客生气离开
flag = 1;
}
if(flag)
printf("0\n");
else
printf("%I64d\n",sum);
}
}
return 0;
}