Description
Solution
考虑每个有买卖的日子,对于一个魂导器的贡献,它其实是一条直线。
那么对于每个日子,加入合法的直线,在线段树上更新即可。
Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#define fo(i,j,k) for(int i=j;i<=k;++i)
#define fd(i,j,k) for(int i=j;i>=k;--i)
#define ll long long
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
using namespace std;
const int N=1e5+10;
const ll inf=1e15;
vector<int> b[N];
struct node{
int d,p,r,g;
}a[N];
struct line{
int k;
ll b;
ll f(int x){
return (ll)k*x+b;
}
}ln[N];
struct tree{
int l,r,o;
}tr[N*50];
int tot=1,cnt=0;
int n,C,D,m=0;
bool cmp(node x,node y){
return x.d<y.d;
}
double meet(int x,int y){
return (ln[y].b-ln[x].b)*1.0/(ln[x].k-ln[y].k);
}
int change(int v,int l,int r,int x){
if(!v) v=++tot;
if(!tr[v].o) {tr[v].o=x;return v;}
int o=tr[v].o;
double p=meet(x,o);
int mid=(l+r)>>1;
if(p<=l*1.0 || p>=r*1.0 || ln[x].k==ln[o].k){
if(ln[x].f(mid)>ln[o].f(mid)) tr[v].o=x;
return v;
}
if(p<=mid*1.0){
if(ln[x].k>ln[o].k) tr[v].o=x,tr[v].l=change(tr[v].l,l,mid,o);
else tr[v].l=change(tr[v].l,l,mid,x);
}
else{
if(ln[x].k<ln[o].k) tr[v].o=x,tr[v].r=change(tr[v].r,mid+1,r,o);
else tr[v].r=change(tr[v].r,mid+1,r,x);
}
return v;
}
ll find(int v,int l,int r,int x){
if(!v) return -inf;
int o=tr[v].o;
if(!o) return -inf;
ll tmp=ln[o].f(x);
if(l==r) return tmp;
int mid=(l+r)/2;
if(x<=mid) return max(tmp,find(tr[v].l,l,mid,x));
else return max(tmp,find(tr[v].r,mid+1,r,x));
}
void add(int k,ll b){
ln[++cnt].k=k,ln[cnt].b=b;
change(1,1,D+1,cnt);
}
int d[N];
int main()
{
freopen("practice.in","r",stdin);
freopen("practice.out","w",stdout);
int num,Q;
scanf("%d %d",&num,&Q);
while(Q--){
scanf("%d %d %d",&n,&C,&D);
fo(i,1,n) scanf("%d %d %d %d",&a[i].d,&a[i].p,&a[i].r,&a[i].g);
sort(a+1,a+n+1,cmp);
m=0;
fo(i,1,n){
if(a[i].d>D) break;
a[i].d!=a[i-1].d?d[++m]=a[i].d:m;
b[m].push_back(i);
}
cnt=0,add(0,C);
fo(i,1,m){
int o=b[i].size();
ll now=find(1,1,D+1,d[i]);
fo(j,0,o-1){
int p=b[i][j];
if(a[p].p<=now) add(a[p].g,-1ll*a[p].g*d[i]+now-a[p].p+a[p].r-a[p].g);
}
}
ll ans=find(1,1,D+1,D+1);
printf("%lld\n",ans);
mem(tr),mem(ln),mem(d),tot=1;
fo(i,1,m) b[i].clear();
}
}