1 条题解

  • 0
    @ 2025-8-24 22:30:29

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Miko35
    阿玮你又在打电动喔,去看会书好不好

    搬运于2025-08-24 22:30:29,当前版本为作者最后更新于2021-04-08 09:31:29,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    upd:改正了一处笔误(将 l 打成了 1

    验题人又来水题解了。

    for(rgi i=1;i<=n;++i){
    	for(rgi j=1;j<=i;++j)dp[i]=max(dp[i],dp[j-1]+sum(j,i,ma[j][i]));
    }
    

    考虑这个 n2n^2 的 dp,其中 dpidp_i 表示前 ii 个数的答案,sum(l,r,x)\textrm{sum}(l,r,x) 表示“将 [l,r][l,r] 都改为 xx 取得的收益”,mal,rma_{l,r} 表示 [l,r][l,r] 的 range_max。

    看似不大能优化,其实是可以的。记 sl,r=sum(l,r,mal,r)s_{l,r}=\textrm{sum}(l,r,ma_{l,r}),也就是“在 [l,r][l,r] 举行一场作弊的收益”。令 tt 时刻的 SiS_i 表示 si,ts_{i,t},只要我们在 dp 的过程中能随着时间有效维护 SS 数组,就可以使用线段树优化这个 dp 解决问题。

    考虑分开计算每个人的贡献。对于一个人 (ax,lx,rx)(a_x,l_x,r_x),它对一个区间 [L,R][L,R] 产生贡献当且仅当 maL,R[lx,rx],x[L,R]ma_{L,R}\in [l_x,r_x],x\in [L,R]

    把它写成 max(maL,x,max,R)[lx,rx]\max(ma_{L,x},ma_{x,R})\in [l_x,r_x],换句话说也就是:maL,x,max,Rma_{L,x},ma_{x,R} 都要 rx\leq r_x,且其中至少一个 lx\geq l_x

    我们分别预处理出 maL,x,max,R[lx,rx]ma_{L,x},ma_{x,R}\in [l_x,r_x]L,RL,R 的范围,记为 [Llx,Lrx],[Rlx,Rrx][Ll_x,Lr_x],[Rl_x,Rr_x]。所以当 i[x,Rlx)i\in[x,Rl_x) 时,LL 的范围是 [Llx,Lrx][Ll_x,Lr_x];当 i[Rlx,Rrx]i\in[Rl_x,Rr_x] 时,LL 的范围是 [Llx,x][Ll_x,x];当 i>Rrxi>Rr_x 时,没有贡献。

    我们在 ii 到达几个临界点的时候,通过线段树的区间加操作更新 xx 的贡献区间即可。

    这样的复杂度是 O(nlogn)O(n \log n),可以通过此题。

    核心代码:

    for(rgi i=1;i<=n;++i){
    	if(a[i][0]>r[i])continue;
    	ll[i]=lr[i]=rl[i]=rr[i]=i;
    	for(rgi w=LOG;~w;--w){
    		chg(rl[i],w,l[i]-1,1),chg(rr[i],w,r[i],1);
    		chg(lr[i],w,l[i]-1,-1),chg(ll[i],w,r[i],-1);
    	}
    	if(a[lr[i]][0]<l[i])--lr[i];
    	if(a[rl[i]][0]<l[i])++rl[i];
    	v[i].push_back(opt{ll[i],lr[i],1});
    	v[rl[i]].push_back(opt{lr[i]+1,i,1});
    	v[rr[i]+1].push_back(opt{ll[i],i,-1});
    }
    for(rgi i=1;i<=n;++i){
    	for(opt o:v[i])upd(o);
    	upd(opt{i+1,i+1,ans=qry(1,0,n,0,n)});
    }
    
    • 1

    信息

    ID
    6285
    时间
    1000ms
    内存
    500MiB
    难度
    5
    标签
    (无)
    递交数
    0
    已通过
    0
    上传者