专栏文章
题解:P5665 [CSP-S2019] 划分
P5665题解参与者 2已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @miowwdlx
- 此快照首次捕获于
- 2025/12/03 02:28 3 个月前
- 此快照最后确认于
- 2025/12/03 02:28 3 个月前
因为 ,所以要尽可能多分段。
令 表示 的区间和, 表示 的前缀和。
若 ,则 ,那么说明一个区间与前面合并一定优于与后面合并。
所以最后一段要尽可能的小。
设 表示前 个数的答案, 表示前 个数最优情况下划分的最后一段的左端点。
那么对于 ,我们需要找到最大的 ,使得 。
两边同时加 ,得到 。
由于 单调不减,所以显然可以单调队列优化。
对于任意的 ,若 ,那么无论在什么情况下 都不会被选择,直接踢出单调队列。
所以单调队列里的元素一定是根据 单增的。
每个元素最多分别进出单调队列一次,时间复杂度 。
CPPint n; bool ty;
ULL pre[N];
__int128 ans;
int b[N],p[M],l[M],r[M];
int q[N],g[N];
LL calc(int p){return 2*pre[p]-pre[g[p]-1];}
void solve(){
cin>>n>>ty;
if(!ty){
ULL a;
for1(i,1,n) {rin(a); pre[i]=pre[i-1]+a;}
}else{
int x,y,z,m;
cin>>x>>y>>z>>b[1]>>b[2]>>m;
for1(i,1,m) cin>>p[i]>>l[i]>>r[i];
for1(i,3,n) b[i]=(1ll*b[i-1]*x+1ll*b[i-2]*y+z)%mod;
for1(i,1,m)
for1(j,p[i-1]+1,p[i])
pre[j]=pre[j-1]+b[j]%(r[i]-l[i]+1)+l[i];
}
int h=1,t=1;
for1(i,1,n){
while(pre[i]>=calc(q[h+1])&&h<t) h++;
g[i]=q[h]+1;
while(calc(i)<=calc(q[t])&&h<=t) t--;
q[++t]=i;
}
int pos=n;
while(pos){
__int128 qwq=pre[pos]-pre[g[pos]-1];
ans+=qwq*qwq;
pos=g[pos]-1;
}
rout(ans);
return ;
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...