题目链接:http://acm.uestc.edu.cn/problem.php?pid=1558
题目大意:star一开始有1元,他可以通过一次交换(v,r,t)来增加自己的资金,v(1~10^9)表示得到的资金,r(1~10^9)表示交换耗去的资金,t(1~10^9)表示该次交换耗费的时间,给定n(1~10^5)种交换,star最后至少有m(1~10^9)元,求达到要求的最小时间.
思路:这有点像背包问题,和背包不同在于,他的取是有限制的,必须r不可以超过star当前的资金数,但是状态方程是类似的.dp[i]=min(dp[j])+t[i],i第i种交换获得的资金数,j同理且j<i,t[i]则为第i次交换所耗费的时间,显然dp[]存的就是时间.难点在于获取min(dp[j]).(1)资金数的范围很广,离散一下,不然数组开不下.(2)快速获取数组中某一段的min值,显然可以用线段树.
代码:
#include <stdlib.h> #include <string.h> #include <stdio.h> #include <ctype.h> #include <math.h> #include <time.h> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <string> #include <iostream> #include <algorithm> using namespace std; //#define ull unsigned __int64 //#define ll __int64 #define ull unsigned long long #define ll long long #define son1 New(p.xl,xm,p.yl,ym),(rt<<2)-2 #define son2 New(p.xl,xm,min(ym+1,p.yr),p.yr),(rt<<2)-1 #define son3 New(min(xm+1,p.xr),p.xr,p.yl,ym),rt<<2 #define son4 New(min(xm+1,p.xr),p.xr,min(ym+1,p.yr),p.yr),rt<<2|1 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define middle (l+r)>>1 #define MOD 1000000007 #define esp (1e-8) const int INF=0x3FFFFFFF; const ll LINF=0x3FFFFFFFFFFFFFFF; const double DINF=10000.00; //const double pi=acos(-1.0); const int N=100010; int n,m,tot; ll M,X[N<<1],mmin[N<<3],cov[N<<3]; struct node{ ll v,r,t; void write(){ scanf("%lld%lld%lld",&v,&r,&t); X[m++]=v,X[m++]=r; } bool operator < (const node& tmp)const{ return r < tmp.r; } }a[N]; ll min(ll x,ll y){return x<y? x:y;} int bs(ll key,int size,ll A[]){ int l=0,r=size-1,mid,ret=0; while(l<=r){ mid=middle; if(key>A[mid]) l=mid+1; else if(key<=A[mid]) r=(ret=mid)-1; } return ret; } void Build(int l,int r,int rt){ mmin[rt]=LINF; if(l==r) return; int mid=middle; Build(lson),Build(rson); } void PushUp(int rt){ mmin[rt]=min(mmin[rt<<1],mmin[rt<<1|1]); } void Update(int l,int r,int rt,int p,ll c){ if(l==r){mmin[rt]=min(mmin[rt],c);return;} int mid=middle; if(p<=mid) Update(lson,p,c); else Update(rson,p,c); PushUp(rt); } ll Query(int l,int r,int rt,int L,int R){ if(L<=l && r<=R) return mmin[rt]; int mid=middle; ll ret=LINF; if(L<=mid) ret=min(ret,Query(lson,L,R)); if(mid<R) ret=min(ret,Query(rson,L,R)); return ret; } void init(){ scanf("%d%lld",&n,&M); int i; for(i=m=0;i<n;i++) a[i].write(); sort(a,a+n);sort(X,X+m); for(i=tot=1;i<m;i++)if(X[i]!=X[i-1])X[tot++]=X[i]; m=tot-1;Build(0,m,1); } void sof(){ if(a[0].r>1) puts("-1"); else{ int i; ll tmp_T; Update(0,tot,1,0,0); for(i=0;i<n;i++){ tmp_T=Query(0,m,1,bs(a[i].r,tot,X),m); if(tmp_T==LINF) break; Update(0,m,1,bs(a[i].v,tot,X),tmp_T+a[i].t); } tmp_T=Query(0,m,1,bs(M,tot,X),m); if(tmp_T==LINF) puts("-1"); else printf("%lld\n",tmp_T); } } int main(){ //freopen("1.in","r",stdin); //freopen("1.out","w",stdout); int T,cas=0;scanf("%d",&T);for(cas=1;cas<=T;cas++){ init(); printf("Case #%d: ",cas); sof(); } return 0; }