题解 P9499 「RiOI-2」change
写一个 dp 做法。
首先有一个很暴力的 dp,设
尝试直接维护这个 dp,首先我们把
接下来考虑 dp 的时候我们在干什么,设
首先可以发现
接下来要做的是将坐标除以这一段最右点的
考虑这个做法的复杂度,除以
// Problem: T351677 「RiOI-2」change
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/T351677?contestId=122187
// Memory Limit: 512 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define poly vector<int>
#define IOS ios::sync_with_stdio(false)
#define ll __int128
#define mp make_pair
#define mt make_tuple
#define pa pair < int,int >
#define fi first
#define se second
#define inf 1e18
#define mod 998244353
#define sz(x) (int)((x).size())
#define int ll
#define N 200005
using namespace std;
inline char gc(){static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
#define gc getchar
inline ll read(){char c=gc();ll su=0,f=1;for (;c<'0'||c>'9';c=gc()) if (c=='-') f=-1;for (;c>='0'&&c<='9';c=gc()) su=su*10+c-'0';return su*f;}
inline void write(ll x){if (x<0){putchar('-');write(-x);return;}if (x>=10) write(x/10);putchar(x%10+'0');}
inline void writesp(ll x){write(x),putchar(' ');}
inline void writeln(ll x){write(x);putchar('\n');}
int n,a[N],b[N],x[N],suf[N];
bitset<10000005>vis;
struct node
{
vector<int>x,y;
node()
{
poly().swap(x),poly().swap(y);
}
void ins(int a,int b)
{
while (x.size()>0&&a==x.back()&&b>=y.back()) x.pop_back(),y.pop_back();
if (x.size()>0&&a==x.back()&&b<y.back()) return;
x.push_back(a);
y.push_back(b);
}
void add(int k)
{
int l=0;
int mx=0;
for (int i=1;i<x.size();i++)
{
mx=max(mx,y[i]+x[i]*k);
if ((y[i]-y[i-1])/(x[i]-x[i-1])>=-k)
{
l=i;
}
}
if (l==0) return;
poly xx,yy;
xx.push_back(0);yy.push_back(mx);
for (int i=l;i<x.size();i++)
xx.push_back(x[i]),yy.push_back(y[i]);
x.swap(xx);
y.swap(yy);
}
void selfclr()
{
for (int i=0;i<x.size();i++) vis[i]=0;
int t=0;
for (int i=1;i+1<x.size();i++)
{
if ((y[i]-y[i-1])*(x[i+1]-x[i])==(y[i+1]-y[i])*(x[i]-x[i-1]))
vis[i]=1,t=1;
}
if (!t) return;
poly xx,yy;
for (int i=0;i<x.size();i++)
if (!vis[i])
xx.push_back(x[i]),yy.push_back(y[i]);
x.swap(xx);
y.swap(yy);
}
};
pa all[10000005];
int cnt;
node merge(node x,node y)
{
cnt=0;
for (int i=1;i<x.x.size();i++)
{
all[++cnt]=mp(x.x[i]-x.x[i-1],x.y[i]-x.y[i-1]);
}
for (int i=1;i<y.x.size();i++)
{
all[++cnt]=mp(y.x[i]-y.x[i-1],y.y[i]-y.y[i-1]);
}
node res;
res.ins(0,x.y[0]+y.y[0]);
sort(all+1,all+cnt+1,[&](pa x,pa y)
{
return x.se*y.fi>y.se*x.fi;
});
for (int i=1;i<=cnt;i++)
res.ins(res.x.back()+all[i].fi,res.y.back()+all[i].se);
return res;
}
void outp(node x)
{
for (int i=0;i<x.x.size();i++)
writesp(x.x[i]),writeln(x.y[i]);
puts("");
}
void BellaKira()
{
n=read();
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=n;i++) b[i]=read();
node dp;
dp.x.push_back(0);
dp.y.push_back(0);
node st=dp;
for (int i=1;i<n;i++) x[i]=read();
x[n]=1;
suf[n+1]=-1;
for (int i=n;i>=1;i--)
{
suf[i]=a[i];
if (x[i]==1) suf[i]=max(suf[i],suf[i+1]);
}
for (int i=1;i<n;i++)
{
if (x[i]==1&&suf[i+1]>=suf[i]) b[i+1]+=b[i],b[i]=0;
}
for (int l=1;l<=n;l++)
{
int r=l;
while (r<n&&x[r]==1) r++;
node nw=st;
int sum=0;
for (int i=r;i>=l;i--) sum+=a[i]*b[i];
nw.y[0]=sum;
for (int i=r;i>=l;i--)
if (b[i])
{
nw.ins(nw.x.back()+b[i],sum-a[i]*b[i]);
sum-=a[i]*b[i];
}
dp.add(suf[l]);
nw=merge(dp,nw);
if (r==n)
{
dp=nw;
break;
}
dp=node();
dp.ins(0,nw.y[0]);
for (int i=1;i<nw.x.size();i++)
{
{
if (nw.x[i]/x[r]!=nw.x[i-1]/x[r])
{
dp.ins(nw.x[i]/x[r],nw.y[i]-(nw.y[i]-nw.y[i-1])*(nw.x[i]%x[r])/(nw.x[i]-nw.x[i-1]));
}
}
dp.ins(nw.x[i]/x[r],nw.y[i]);
if (i+1<nw.x.size())
{
if (nw.x[i+1]/x[r]!=nw.x[i]/x[r])
{
dp.ins(nw.x[i]/x[r]+1,nw.y[i]+(x[r]-nw.x[i]%x[r])*(nw.y[i+1]-nw.y[i])/(nw.x[i+1]-nw.x[i]));
}
}
}
dp.selfclr();
l=r;
}
writeln(dp.y[0]%mod);
}
signed main()
{
int id=read();
int T=read();
while (T--)
{
BellaKira();
}
}