vijosP1901学姐的钱包

题目:https://vijos.org/p/1901

题解:这题比较有意思。

         经过一番思考之后我想出了下面的算法:

        我们反着来推,按i从大到小

        f[i]表示从>=m到 i 需要多长时间,则如果v[j]=i,则我们可以用f[i]+t[j] 去更新 r[j]-inf 的所有f值

        由于f[i]是一个单调递减的函数,则我们只需要用它去更新r[j]-i-1即可

        然后问题就变成了区间修改,单点查询,线段树即可

代码:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<iostream>
  7 #include<vector>
  8 #include<map>
  9 #include<set>
 10 #include<queue>
 11 #include<string>
 12 #define inf 100000000000000ll
 13 #define maxn 250000
 14 #define maxm 500+100
 15 #define eps 1e-10
 16 #define ll long long
 17 #define pa pair<int,int>
 18 #define for0(i,n) for(int i=0;i<=(n);i++)
 19 #define for1(i,n) for(int i=1;i<=(n);i++)
 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 22 #define mod 1000000007
 23 using namespace std;
 24 inline int read()
 25 {
 26     int x=0,f=1;char ch=getchar();
 27     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 28     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 29     return x*f;
 30 }
 31 int n,m,a[2*maxn],b[2*maxn],c[2*maxn];
 32 ll ti[maxn];
 33 struct seg{int k,l,r;ll mi,tag;}t[8*maxn];
 34 inline void build(int k,int l,int r)
 35 {
 36     t[k].l=l;t[k].r=r;int mid=(l+r)>>1;
 37     t[k].mi=inf;t[k].tag=inf;
 38     if(l==r)return;
 39     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
 40 }
 41 inline void update(int k,ll z)
 42 {
 43     t[k].tag=min(t[k].tag,z);
 44     t[k].mi=min(t[k].mi,z);
 45 }
 46 inline void pushdown(int k)
 47 {
 48     if(t[k].tag==inf)return;
 49     update(k<<1,t[k].tag);
 50     update(k<<1|1,t[k].tag);
 51     t[k].tag=inf;
 52 }
 53 inline void pushup(int k)
 54 {
 55     t[k].mi=min(t[k<<1].mi,t[k<<1|1].mi);
 56 }
 57 inline void change(int k,int x,int y,ll z)
 58 {
 59     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
 60     if(l==x&&r==y){update(k,z);return;}
 61     pushdown(k);
 62     if(y<=mid)change(k<<1,x,y,z);
 63     else if(x>mid)change(k<<1|1,x,y,z);
 64     else change(k<<1,x,mid,z),change(k<<1|1,mid+1,y,z);
 65     pushup(k);
 66 }
 67 inline ll query(int k,int x)
 68 {
 69     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
 70     if(l==r)return t[k].mi;
 71     pushdown(k);
 72     if(x<=mid)return query(k<<1,x);else return query(k<<1|1,x);
 73 }
 74 inline bool cmp1(int x,int y){return a[x]<a[y];}
 75 inline bool cmp2(int x,int y){return b[x]>b[y];}
 76 int main()
 77 {
 78     freopen("input.txt","r",stdin);
 79     freopen("output.txt","w",stdout);
 80     int cs=read(),mm=0;
 81     while(cs--)
 82     {
 83         n=read();m=read();
 84         for1(i,n)a[i]=read(),a[n+i]=read(),ti[i]=read();a[2*n+1]=m;a[2*n+2]=1;
 85         for1(i,2*n+2)c[i]=i;
 86         sort(c+1,c+2*n+3,cmp1);
 87         int tot=0;
 88         for1(i,2*n+2)
 89         {
 90             if(i==1||a[c[i]]!=a[c[i-1]])tot++;
 91             b[c[i]]=tot;
 92         }
 93         for1(i,n)c[i]=i;
 94         sort(c+1,c+n+1,cmp2);
 95         build(1,1,tot);
 96         change(1,b[2*n+1],tot,0);
 97         for1(i,n)
 98         {
 99             ll x=query(1,b[c[i]]);if(x==inf)continue;
100             if(b[c[i]]>b[n+c[i]])change(1,b[n+c[i]],b[c[i]]-1,x+ti[c[i]]);
101         }
102         ll ans=query(1,b[2*n+2]);
103         printf("Case #%d: ",++mm);
104         if(ans==inf)printf("-1\n");else printf("%lld\n",ans);
105     }
106     return 0;
107 }
View Code

 

posted @ 2014-11-02 12:00  ZYF-ZYF  Views(233)  Comments(0Edit  收藏  举报