测试1T3
题目描述
小天才lyk喜欢玩一个叫pinball的游戏。游戏规则如下:
Pinball的游戏界面由m+2行、n列组成。第一行在顶端。一个球会从第一行出发,开始垂直下落,lyk会得到一个积分当他击中一个球的时候。
小天才lyk觉得这太困难了,于是在界面中放入了一些漏斗,一共有m个漏斗分别放在第2~m+1行,第i个漏斗的作用是把经过第i+1行且列数在Ai~Bi之间的球将其移到第Ci列。
但是使用每个漏斗都是需要付钱的,第i个漏斗需要支付Di的价钱,lyk需要保留一些漏斗,使得球无论从第一行的哪一列开始放,都只可能到达第m+2行的唯一一列。同时,lyk希望花费最小的价钱。
输入
第一行两个数,m和n
接下来m行,第i+1行描述第i个漏斗的属性,Ai,Bi,Ci,Di(1<=Ai<=Ci<=Bi<=n,1<=Di<=1000000000)。
输出
若不存在一种方案能满足条件则输出-1,否则输出最小话费。
样例输入
5 6 2 4 3 5 1 2 2 8 3 6 5 2 4 6 4 7 2 4 3 10 3 5 2 4 3 10 1 3 1 20 2 5 4 30
样例输出
25 -1
提示
【样例解释1】
如图,只需使用第2、4、5个漏斗即可。
【数据范围】
对于20%的数据,m<=10,n<=1000
对于
40%的数据,m<=200
对于60%的数据,m<=1000
对于100%的数据,m<=100000,2<=n<=1000000000
原题等价于第一列和第n列最终掉在同一列上
l[i]表示从第1列到第i列最后使用漏斗i到达c[i]的最小花费
l[i]=min(l[j]:a[i]<=c[j]<=b[i]+d[i]);
这是个离散化的rmq问题
用线段树就行
离散化~~
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> using namespace std; #define ll long long const ll INF=(ll)1<<60; #define N 110000 int n,m,a[N],b[N],c[N],d[N],q[N]; ll ans=INF; struct seg{ ll Min[N*4],a[N]; void build(int u,int l,int r){ if(l==r){ Min[u]=a[l]; return; } int mid=(l+r)>>1; build(u*2,l,mid); build(u*2+1,mid+1,r); Min[u]=min(Min[u*2],Min[u*2+1]); } ll find(int u,int l,int r,int x,int y){ if(x<=l && y>=r)return Min[u]; if(x>r || y<l)return INF; int mid=(l+r)>>1; return min(find(u*2,l,mid,x,y),find(u*2+1,mid+1,r,x,y)); } void change(int u,int l,int r,int x,ll w){ if(l==r){ Min[u]=min(w,Min[u]); return; } int mid=(l+r)>>1; if(x<=mid)change(u*2,l,mid,x,w); else change(u*2+1,mid+1,r,x,w); Min[u]=min(Min[u*2],Min[u*2+1]); } }t1,t2; int bin1(int k){ int l=1,r=q[0]; while(l<r){ int mid=(l+r)/2; if(q[mid]>=k)r=mid; else l=mid+1; } return l; } int bin2(int k){ int l=1,r=q[0]; while(l<r){ int mid=(l+r)/2+1; if(k>=q[mid])l=mid; else r=mid-1; } return l; } int main(){ freopen("pinball.in","r",stdin); freopen("pinball.out","w",stdout); scanf("%d%d",&n,&m); q[++q[0]]=1; q[++q[0]]=m; for(int i=1;i<=n;i++)scanf("%d %d %d %d",&a[i],&b[i],&c[i],&d[i]),q[++q[0]]=c[i]; sort(q+1,q+q[0]+1); q[0]=1; for(int i=2;i<=n+2;i++) if(q[i]!=q[q[0]])q[++q[0]]=q[i]; m=q[0]; for(int i=1;i<=q[0];i++){ t1.a[i]=INF*(int)(i>1); t2.a[i]=INF*(int)(i<q[0]); } t1.build(1,1,q[0]); t2.build(1,1,q[0]); for(int i=1;i<=n;i++){ a[i]=bin1(a[i]); b[i]=bin2(b[i]); c[i]=bin1(c[i]); ll f1=t1.find(1,1,q[0],a[i],b[i]),f2=t2.find(1,1,q[0],a[i],b[i]); ans=min(f1+f2+d[i],ans); t1.change(1,1,q[0],c[i],f1+d[i]); t2.change(1,1,q[0],c[i],f2+d[i]); } if(ans<INF)cout<<ans<<endl; else cout<<-1<<endl; return 0; }