题意:
有n天,每天需要用k个cpu, 然后给定m个计划,对于每个计划包含 L, R, c, p 表示,从第L天到第R天期间,每天你都可以选用c个cpu,每个cpu的花费为p; 问n天的最小花费;(当某天不能得到k个cpu时,就把能选的全选)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <set>
#include <vector>
using namespace std;
int n,k,m;
struct node
{
int id,l,r;
long long c,p;
friend bool operator<(node a,node b)
{
if(a.p==b.p)
return a.id<b.id;
return a.p<b.p;
}
node(){};
node(int idd,int ll,int rr,long long cc,long long pp){
id=idd;l=ll;r=rr;c=cc;p=pp;
}
}itm[200005];
vector<int> in[1000005],out[1000005];
int main() {
while(~scanf("%d%d%d",&n,&k,&m))
{
for(int i=0;i<=1000002;i++)
in[i].clear(),out[i].clear();
set<node> s1,s2;
for(int i=1;i<=m;i++)
{
long long l,r,c,p;
scanf("%lld%lld%lld%lld",&l,&r,&c,&p);
node tp(i,l,r,c,p);
itm[i]=tp;
in[l].push_back(i);
out[r+1].push_back(i);
}
long long anss=0,sum=0,tans=0;
for(int i=1;i<=n;i++)
{
int len1=out[i].size();
for(int j=0;j<len1;j++)
{
int tid=out[i][j];
if(s1.find(itm[tid])==s1.end())
{
s2.erase(itm[tid]);
}
else
{
s1.erase(itm[tid]);
sum-=itm[tid].c;
tans-=itm[tid].c*itm[tid].p;
}
}
int len2=in[i].size();
for(int j=0;j<len2;j++)
{
int tid=in[i][j];
s2.insert(itm[tid]);
}
while((!s1.empty()) && (!s2.empty()))
{
set<node>::iterator it1,it2;
it1=s1.end();it1--;
it2=s2.begin();
if(it1->p>it2->p)
{
sum-=it1->c;tans-=it1->c*(it1->p);
sum+=it2->c;tans+=it2->c*(it2->p);
s1.insert(*it2);
s2.insert(*it1);
s1.erase(it1++);
s2.erase(it2++);
}
else
break;
}
if(sum>=k)
{
while(sum>=k)
{
set<node>::iterator it1=s1.end();
it1--;
if((sum-it1->c)<k)
break;
else
{
sum-=it1->c;
tans-=it1->c*it1->p;
s2.insert(*it1);
s1.erase(it1++);
}
}
}
else
{
while(sum<k && (!s2.empty()))
{
set<node>::iterator it1;
it1=s2.begin();
sum+=it1->c;
tans+=it1->c*it1->p;
s1.insert(*it1);
s2.erase(it1++);
}
}
if(sum>k)
{
set<node>::iterator it1;
it1=s1.end();it1--;
anss+=tans;
anss-=it1->c*it1->p;
long long tnum=k-(sum-it1->c);
anss+=tnum*it1->p;
} else
anss+=tans;
}
printf("%lld\n",anss);
}
return 0;
}