P9499题解
思路
我们从前往后加入
对于一组新的
我们首先将组里从后往前每
然后加入
我们证明这个做法的正确性。
我们首先证明组内关于
其次我们证明这一构造是最优的。具体的,我们可以证明
具体实现中,我们将
代码
#define int __int128
constexpr int p=998244353;
main()
{
signed t;
cin>>t>>t;
while(t--)
{
int n;
cin>>n;
vector<int>c(n),v(n),X(n-1);
cin>>v>>c>>X;
int ans=v[0]*c[0];
vector<pair<int,int>>p;
p.push_back({v[0],c[0]});
for(int x=1;x<n;x++)
{
if(X[x-1]>1)
{
vector<pair<int,int>>p_;
int lst=0,llst=0;
while(!p.empty())
{
auto [u,v]=p.back();
p.pop_back();
if(lst!=0)
{
int fk=min(v,X[x-1]-llst);
lst+=fk*u;
llst+=fk;
v-=fk;
if(lst>1e10)break;
if(llst==X[x-1])p_.push_back({lst,1}),lst=llst=0;
else continue;
}
if(u*X[x-1]<=1e10)p_.push_back({u*X[x-1],v/X[x-1]}),v%=X[x-1];
else break;
lst=u*v;llst=v;
}
swap(p,p_);
reverse(p.begin(),p.end());
}
ans+=v[x]*c[x]%(::p);
while(!p.empty()&&p.back().first<=v[x])
ans+=p.back().second*(v[x]-p.back().first)%(::p),c[x]+=p.back().second,p.pop_back();
p.push_back({v[x],c[x]});
}
cout<<ans%(::p)<<endl;
}
}
注:这是这份代码的头。