首页 > 代码库 > Vijos1901学姐的钱包
Vijos1901学姐的钱包
描述
学姐每次出门逛街都要带恰好M元钱, 不过她今天却忘记带钱包了.
可怜的doc只好自己凑钱给学姐, 但是他口袋里只有一元钱.
好在doc的N位朋友们都特别有钱, 他们答应与doc作一些交换.
其中第i位朋友说:
如果doc有不少于Ri元钱,
doc可以把手上所有的钱都给这位朋友,
并从这位朋友手中换回Vi元钱,
但是这次交换会浪费Ti的时间.
doc希望可以在最短的时间内换到M元钱(其实是可以大于M的, 因为doc可以存私房钱呢), 否则学姐会生气的!
格式
输入格式
输入数据第一行给定T, 表示总的询问次数.
对于每一次询问, 第一行给出两个整数N和M.
之后N行, 每一行给出三个整数Vi, Ri和Ti. (保证Ri<=Vi).
输出格式
对于每一次询问, 首先输出询问的编号, 参见样例输出.
之后输出最小需要的时间, 如果不可能完成目标, 则输出-1.
思路: 被这道题赤裸裸的坑了一上午,思路很清晰,但是。。。写的很渣。有点像有价值的线段覆盖,将线段右端点排序,离散之后对每一条线段的左右端点之间查询最小值,然后更新右端点处的最小值,最后,找到m到最右端的最小值就好了。这个过程用到了线段树,可是写的很渣,还是要好好学习啊。。。
(一开始,离散的时候,将左右端点都离散了,结果赤裸裸的只过了样例;后来只将右端点离散,然后用lower_bound就过了。。。哪位神犇能知道为什么?!!!)
code:
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
struct use{
int li,ri,ti;
}a[500000];
int c[500000]={0};
long long tree[800001]={0},maxn=0x7ffffffffffffff;
int my_comp(const use &x,const use &y)
{
if (x.ri<y.ri) return 1;
return 0;
}
void build(int i,int l,int r)
{
int mid;
if (l!=1) tree[i]=maxn;
else tree[i]=0;
if (l!=r)
{
mid=(l+r)/2;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
}
}
long long work(int i,int l,int r,int ll,int rr)
{
int mid;
long long minn;
if (ll<=l&&r<=rr)
return tree[i];
mid=(l+r)/2;
minn=maxn;
if (ll<=mid)
minn=min(minn,work(i*2,l,mid,ll,rr));
if (rr>mid)
minn=min(minn,work(i*2+1,mid+1,r,ll,rr));
return minn;
}
void insert(int i,int l,int r,int ll,long long k)
{
int mid;
if (l==r)
{
tree[i]=k;
return;
}
mid=(l+r)/2;
if (ll<=mid)
insert(i*2,l,mid,ll,k);
if (ll>mid)
insert(i*2+1,mid+1,r,ll,k);
tree[i]=min(tree[i*2],tree[i*2+1]);
}
int main()
{
int ci,t,i,j,n,m,size;
long long ans,minn;
scanf("%d",&t);
for (ci=1;ci<=t;++ci)
{
scanf("%d%d",&n,&m);
for (i=1;i<=n;++i)
scanf("%d%d%d",&a[i].ri,&a[i].li,&a[i].ti);
sort(a+1,a+n+1,my_comp);
c[1]=1;
for (i=1;i<=n;++i)
c[i+1]=a[i].ri;
size=unique(c+1,c+n+2)-c-1;
build(1,1,size);
for (i=1;i<=n;++i)
if (a[i].ri>a[i].li)
{
a[i].ri=lower_bound(c+1,c+size+1,a[i].ri)-c;
minn=work(1,1,size,lower_bound(c+1,c+size+1,a[i].li)-c,a[i].ri);
if (minn!=maxn) insert(1,1,size,a[i].ri,minn+a[i].ti);
else break;
}
printf("Case #%d: ",ci);
ans=work(1,1,size,lower_bound(c+1,c+size+1,m)-c,size);
if (ans!=maxn)
printf("%lld\n",ans);
else printf("-1\n");
}
}
Vijos1901学姐的钱包