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 }