传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6408
一上场读完这题,大概是个费用流防AK题吧,果然晚上dls讲题也说他第一眼费用流线段树加速找增广路(这什么东西哇,然后就跳过了,比完赛看了题解后,感觉以前noip最后3套模拟,cy的题有一道勇者斗恶龙也是这样,先不管用没用,先放进一个堆了,要用的时候再取最优的出来,算一蛤代价。这题有几个需要想到的结论,由于材料是无限的,那么c[i]更新为c[i-1]+R[i]表示从古至今最便宜的材料价格是多少,加上保存时间代价,那么这样我们当天生产的电脑的费用就是c[i]了,放进set中,我们还有一个保存电脑的费用,所以这个月卖ind月的电脑所要的费用是cost+pre[i-1]-pre[ind-1],表示从ind月生产出来的费用再加上每天保存的费用,总共费用是多少一台。那么每天晚上清仓的时候,我们把假设生产出来的电脑中费用最多的丢掉,只保留少于或等于e[i]台花费最小的假设生产出来的电脑。
attention:set里面装结构体,重载运算符要记住每个元素都要判不同,因为根据你的比大小要是相同了set就不会装进去了,set会把比大小相同的元素只装一个。
node x=(*s.begin())会把第一个元素的值赋值给x,x是个单独的结构体变量,x值的变化不会对s有影响
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#define maxl 50010
using namespace std;
int k;
int c[maxl],d[maxl],m[maxl],p[maxl],e[maxl],R[maxl],E[maxl];
long long ans;
long long pre[maxl];
struct node
{
int cost,res,ind;
bool operator < (const node b) const
{
if(b.ind<ind)
{
if(cost!=pre[ind-1]-pre[b.ind-1]+b.cost)
return cost<pre[ind-1]-pre[b.ind-1]+b.cost;
else
return ind<b.ind;
}
else
{
if(cost+pre[b.ind-1]-pre[ind-1]!=b.cost)
return cost+pre[b.ind-1]-pre[ind-1]<b.cost;
else
return ind<b.ind;
}
}
};
set <node> s;
set <node> ::iterator it;
bool flag;
inline int min(int a,int b)
{
if(a<b)
return a;
else
return b;
}
inline void prework()
{
scanf("%d",&k);
for(int i=1;i<=k;i++)
scanf("%d%d%d%d",&c[i],&d[i],&m[i],&p[i]);
for(int i=1;i<=k-1;i++)
scanf("%d%d%d",&e[i],&R[i],&E[i]);
int minic=c[1];
for(int i=2;i<=k;i++)
c[i]=min(c[i-1]+R[i-1],c[i]);
for(int i=1;i<=k-1;i++)
pre[i]=pre[i-1]+E[i];
s.clear();
}
inline void prints()
{
for(it=s.begin();it!=s.end();++it)
printf("%d %d\n",it->cost,it->res);
}
inline void mainwork()
{
int sum=0,num;flag=true;node x;ans=0;
for(int i=1;i<=k;i++)
{
x.cost=c[i]+m[i];x.res=p[i];x.ind=i;
s.insert(x);
//prints();//打印set
sum+=p[i];
while(d[i])
{
if(sum==0 || s.begin()==s.end())
{
flag=false;
return;
}
it=s.begin();
x=(*it);
//x.cost=it->cost;x.res=it->res;x.ind=it->ind;
s.erase(it);
//prints();//打印set
if(x.res>d[i])
{
ans+=(x.cost+pre[i-1]-pre[x.ind-1])*d[i];
x.res-=d[i];sum-=d[i];d[i]=0;
s.insert(x);
//prints();//打印set
}
else
{
ans+=(x.cost+pre[i-1]-pre[x.ind-1])*x.res;
d[i]-=x.res;sum-=x.res;x.res=0;
}
}
num=sum-e[i];
while(num>0)
{
it=s.end();it--;
x=(*it);
//x.cost=it->cost;x.res=it->res;x.ind=it->ind;
s.erase(it);
if(x.res>num)
sum-=num,x.res-=num,num=0,s.insert(x);
else
sum-=x.res,num-=x.res;
}
}
}
inline void print()
{
if(flag)
printf("%lld\n",ans);
else
printf("-1\n");
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}