首页 > 代码库 > vijosP1901学姐的钱包

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

 

vijosP1901学姐的钱包