hdu 4122 Alice's mooncake shop题解


题目大意:一个月饼店开m个小时(24小时营业),只在整点做月饼,做月饼的能力非常强。现在只需要考虑成本的问题。给m个cost值,cost[i]表示第i个小时做1个月饼的代价。
 
再给n个时间,从2000年1月1日0时开始计算。表示订单的截止时间。当然为了节约成本,可以提前趁成本不高的时候做月饼。但是月饼有保质期,t天,月饼放冰箱保存也需要代价,一天花费s。现在求完成n个订单最小代价。
 
题目分析:对于第i个订单,首先计算出是第ti个营业时间。这里考虑每个月饼的单价。所以第i个订单的月饼只能在(ti - t,ti]做。考虑时间j有个订单,假设时间i完成代价是最小的。那么第j个订单的代价就是cost[i] + (j - i) * s,整理一下:cost[i] - i*s + j*s,这里我们只需要维护cost[i] - i*s即可。即维护(订单时间-t,订单时间]这个区间里的cost[i] - i*s的最小值即可。所以可以用单调队列或者线段树来维护。
线段树:
//hdu4122Alice's mooncake shop(单调队列 | 线段树)
#include
#include
#include
#define LL long long int
#define inf 0x7f7f7f7f
#define MAX 100009
using namespace std;
struct Node{
    char str[10];
    LL a,b,c,x,hour;
}mapp[3000];
LL cost[100009];
map month;
LL minV;
LL n,m,T,S;
int mon[]={31,28,31,30,31,30,31,31,30,31,30,31};//每个月的天数
struct point{
	LL minV;
	LL maxV;
	LL L;
	LL R;
	LL mid(){
		return (L+R)/2;
	}
}tree[MAX*4];
void build(LL root, LL s,LL e){
	tree[root].L=s;
	tree[root].R=e;
	tree[root].minV=inf;
	if(tree[root].L!=tree[root].R){
		build(root*2,s,tree[root].mid());
		build(root*2+1,tree[root].mid()+1,e);
	}
}
//cost[i] - i*s
void insert(LL root, LL pos, LL val){
	if(tree[root].L==tree[root].R){
		tree[root].minV=val;
		return;
	}
	if(pos<=tree[root].mid()){
		insert(root*2, pos, val);
	}else{
		insert(root*2+1,pos,val);
	}
	tree[root].minV=min(tree[root*2].minV,tree[root*2+1].minV);
}
void query(LL root, LL s, LL e){
	if(tree[root].L==s&&tree[root].R==e){
		minV=min(tree[root].minV,minV);
		return ;
	}
	if(e<=tree[root].mid()){
		query(root*2,s,e);
	}else if(s>tree[root].mid()){
		query(root*2+1,s,e);
	}else{
		query(root*2,s,tree[root].mid());
		query(root*2+1,tree[root].mid()+1,e);
	}
}
bool isleap(int t){
    if(t%400==0||(t%100!=0&&t%4==0)) return true;
    return false;
}
LL gettime(int t){
    LL day=0;
    for(int i=2000;i

RMQ:
//hdu4122Alice's mooncake shop(单调队列 | 线段树)
#include
#include
#include
#include
#define LL long long int
#define inf 0x7f7f7f7f
#define MAX 100009
using namespace std;
struct Node{
    char str[10];
    LL a,b,c,x,hour;
}mapp[3000];
LL cost[100009];
map month;
LL minV;
LL n,m,T,S;
LL dp[100009][20];
int mon[]={31,28,31,30,31,30,31,31,30,31,30,31};//每个月的天数
bool isleap(int t){
    if(t%400==0||(t%100!=0&&t%4==0)) return true;
    return false;
}
LL gettime(int t){
    LL day=0;
    for(int i=2000;i


你可能感兴趣的:(线段树,RMQ)