怎么网上题解都是cdq分治做的啊。。。
题意什么的最近都懒得写了。。看这里http://blog.csdn.net/sdj222555/article/details/40919903
n方暴力很好想,f[i]= f[j] + (d[i]-d[j]-1) * G[j] + R[j] - P[i] 。
写成向量点积形式 f[i]= ( d[i] , 1 ) * ( G[j] , f[j]+R[j]-(d[j]+1])*G[j] ) - p[i] 。
把所有的 j 都 扔到平衡树里维护个上凸壳 就好了。
注意到 d[i] 是递增的,于是也不需要二分查找了。
貌似还是cdq写起来简单点?不过平衡树好想啊。
#include<cstdio>
#include<map>
#include<algorithm>
#define X first
#define Y second
using namespace std;
typedef long long ll;
typedef map<ll,ll>::iterator itr;
struct P
{
ll x,y;
P operator-(const P &t)const
{
return {x-t.x,y-t.y};
}
ll operator^(P t)
{
return x*t.y-y*t.x;
}
};
ll dot(itr it,ll x,ll y)
{
return it->X*x+it->Y*y;
}
ll cross(itr l,P p2,itr r)
{
P p1={l->X,l->Y},p3={r->X,r->Y};
return (p2-p1)^(p3-p2);
}
struct hull
{
map<ll,ll>s;
itr mid,l,r,p1,p2;
void init() { s.clear(); }
itr pre(itr it)
{
if (it==s.end()) return it;
if (it==s.begin()) return s.end();
return --it;
}
itr suc(itr it)
{
if (it==s.end()) return it;
return ++it;
}
bool inside(P p)
{
if (s.empty()) return 0;
r=s.lower_bound(p.x);
if (r==s.end()) return 0;
if (r->X==p.x) return p.y<=r->Y;
if (r==s.begin()) return 0;
l=r; l--;
return cross(l,p,r)>=0;
}
void add(P p)
{
if (inside(p)) return;
s[p.x]=p.y;
mid=s.find(p.x);
p1=suc(mid); p2=suc(p1);
while(p1!=s.end()&&p2!=s.end()&&cross(mid,{p1->X,p1->Y},p2)>=0)
s.erase(p1),p1=p2,p2=suc(p2);
p1=pre(mid); p2=pre(p1);
while(p1!=s.end()&&p2!=s.end()&&cross(mid,{p1->X,p1->Y},p2)<=0)
s.erase(p1),p1=p2,p2=pre(p2);
}
ll get(ll x,ll y)
{
l=s.begin();
r=suc(l);
while(r!=s.end()&&dot(l,x,y)<=dot(r,x,y))
s.erase(l),l=r,r=suc(r);
return dot(l,x,y);
}
}G;
const int N=100005;
int n,C,D;
struct mac
{
int d,P,R,G;
}a[N];
bool cmp(mac a,mac b){ return a.d<b.d;}
ll f[N];
int main()
{
int cas=0;
while(scanf("%d%d%d",&n,&C,&D),n+C+D)
{
for (int i=1;i<=n;i++)
scanf("%d%d%d%d",&a[i].d,&a[i].P,&a[i].R,&a[i].G);
sort(a+1,a+n+1,cmp);
a[0]={0,0,0,0};
f[0]=C;
n++;
a[n]={D+1,0,0,0};
G.init();
G.add({a[0].G,f[0]});
for (int i=1;i<=n;i++)
{
f[i]=G.get(a[i].d,1)-a[i].P;
if (f[i]>=0) G.add({a[i].G,f[i]+a[i].R-1ll*(a[i].d+1)*a[i].G});
}
printf("Case %d: %lld\n",++cas,f[n]);
}
}