= = 虽然这题并不太难调 可我还是调了一年呀。。
一个区间DP+平衡树维护。因为空间不太够,所以点合并起来(就像NOIP2017列队一样)。
然后用的时候拆开,最多2e5个点。
考虑状态 f[l][r][i][j] f [ l ] [ r ] [ i ] [ j ] 为l-r区间内用了从i到j的方案的最大价值。转移显然。。然后就在平衡树上调就好了= =然后你要注意update时不要写反,拆点时尽量不要递归。。别写错点的标号等等等等错误。。。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
typedef pair<ll,ll>par;
const ll MAXN=5e5+5;
struct data{
ll f[4][4];
ll getans(){
ll ans=0;
for(ll i=0;i<=3;i++){
for(ll j=i;j<=3;j++){
ans=max(ans,f[i][j]);
}
}
return ans;
}
};
data operator + (data a,data b){
data c;
for(ll i=0;i<=3;i++){
for(ll j=i;j<=3;j++){
c.f[i][j]=0;
for(ll k=i;k<=j;k++){
// cout<<a.f[i][k]<<" "<<i<<":"<<j<<":"<<k<<endl;
c.f[i][j]=max(a.f[i][k]+b.f[k][j],c.f[i][j]);
}
}
}
return c;
}
struct Treap{
ll size[MAXN],prio[MAXN],lson[MAXN],rson[MAXN],ai[MAXN],bi[MAXN],ci[MAXN],si[MAXN],rt,cnt;
data d[MAXN],g[MAXN];
inline void pushup(ll o){
ll l=lson[o],r=rson[o];
size[o]=size[l]+size[r]+si[o];
g[o]=d[o];
if(l)g[o]=g[l]+g[o];
if(r)g[o]=g[o]+g[r];
}
inline ll newnode(ll a,ll b,ll c,ll num){
++cnt;
size[cnt]=num;prio[cnt]=rand();lson[cnt]=rson[cnt]=0;
ai[cnt]=a,bi[cnt]=b,ci[cnt]=c;si[cnt]=num;
d[cnt].f[0][0]=d[cnt].f[3][3]=a*num;
d[cnt].f[1][1]=b*num;d[cnt].f[2][2]=c*num;
for(ll i=0;i<=3;i++){
for(ll j=i+1;j<=3;j++){
d[cnt].f[i][j]=max(d[cnt].f[i][j-1],d[cnt].f[j][j]);
}
}
return cnt;
}
ll merge(ll x,ll y){
if(!x){pushup(y);return y;}
if(!y){pushup(x);return x;}
if(prio[x]<prio[y]){
rson[x]=merge(rson[x],y);pushup(x);return x;
}
lson[y]=merge(x,lson[y]);pushup(y);return y;
}
par split(ll p,ll x){
if(!x)return mp(0,p);
ll l=lson[p],r=rson[p];
if(x<=size[l]){
par tem=split(l,x);
lson[p]=tem.second;pushup(p);return mp(tem.first,p);
}
else if(x>=size[l]+si[p]){
par tem=split(r,x-size[l]-si[p]);
rson[p]=tem.first;pushup(p);return mp(p,tem.second);
}
//par tem=split(l,size[l]);
//par tem2=split(r,size[p]-size[l]-si[p]);
//ll p1=newnode(ai[p],bi[p],ci[p],x-size[l]);
// ll p2=newnode(ai[p],bi[p],ci[p],si[p]-x+size[l]);
ll pre=si[p];si[p]=x-size[l];
d[p].f[0][0]=d[p].f[3][3]=ai[p]*si[p];
d[p].f[1][1]=bi[p]*si[p];d[p].f[2][2]=ci[p]*si[p];
for(ll i=0;i<=3;i++){
for(ll j=i+1;j<=3;j++){
d[p].f[i][j]=max(d[p].f[i][j-1],d[p].f[j][j]);
}
}
ll p1=newnode(ai[p],bi[p],ci[p],pre-si[p]);p1=merge(p1,r);rson[p]=0;
pushup(p);pushup(p1);
//cout<<p1<<":"<<endl;
return mp(p,p1);
}
void insert(ll p,ll a,ll b,ll c,ll x){
par tem=split(rt,p);
ll dq=newnode(a,b,c,x);
ll t=merge(tem.first,dq);
rt=merge(t,tem.second);
// cout<<rt<<":";debug(rt);
}
void debug(ll p){
if(lson[p])debug(lson[p]);
cout<<p<<" "<<ai[p]<<endl;
if(rson[p])debug(rson[p]);
}
}T;
int main(){
// freopen("amane.in","r",stdin);
// freopen("amane.out","w",stdout);
srand(19260817);
ll n;
scanf("%lld",&n);
ll Now=0,Last=0;
ll t1,t2,t3,t4,t5;
scanf("%lld%lld%lld%lld%lld",&t1,&t2,&t3,&t4,&t5);
T.rt=T.newnode(t2,t3,t4,t5);
Last=T.d[T.rt].getans();
printf("%lld\n",Last);
for(ll i=2;i<=n;i++){
ll t1,t2,t3,t4,t5;
scanf("%lld%lld%lld%lld%lld",&t1,&t2,&t3,&t4,&t5);
T.insert(t1,t2,t3,t4,t5);
Now=T.g[T.rt].f[0][3];
//cout<<Now<<"sas"<<endl;
printf("%lld\n",Now-Last);
Last=Now;
}
return 0;
}
/*
5
0 25 37 46 2
1 32 14 16 3
3 99 77 88 4
2 43 68 57 5
14 72 36 18 6
*/