acm-(差分、暴力、序列)Educational Codeforces Round 98 E. Two Editorials

题面
传送门

本质上就是找两个长度为 k k k的窗口算贡献。

考虑先固定第一个窗口位于 [ L , R ] ( R − L + 1 = k ) [L,R](R-L+1=k) [L,R](RL+1=k),然后暴力遍历 ( l i , r i ) (l_i,r_i) (li,ri),考虑它们对第一个窗口的总贡献为 s m sm sm,然后考虑第二个窗口位于每个位置上的时候对应的附加贡献, s m sm sm和附加贡献加起来后取 m a x max max即可。

本题的难点在于如何快速计算 ( l i , r i ) (l_i,r_i) (li,ri)对于第二个窗口在每个位置上的贡献。这里运用差分的方法。对于特定的 ( l , r ) (l,r) (l,r)而言,假设第一个窗口 [ L , R ] [L,R] [L,R]对它的覆盖区间长度是 w w w,那么当第二个窗口与 ( l , r ) (l,r) (l,r)的覆盖区间长度小于等于 w w w的时候我们可以认为 ( l , r ) (l,r) (l,r)对第二个窗口的附加贡献是0,但是 > w >w >w的时候我们就需要考虑对于第二个窗口的附加贡献了。
考虑枚举第二个窗口的右端点从小到大,根据滑动窗口的思想,每次滑动一格位置都需要考虑一下新增加的贡献和要删除的贡献。不过这些贡献来自于 ( l i , r i ) (l_i,r_i) (li,ri),故干脆考虑 ( l i , r i ) (l_i,r_i) (li,ri)会对第二个窗口在哪些位置产生贡献即可,进行区间加减操作,不过区间加可以改成修改差分数组。

具体来说,对于 ( l , r ) (l,r) (l,r)而言,需要考虑当第二个滑动窗口位于 R ′ R' R位置(正在接近 ( l , r ) (l,r) (l,r))的时候,会对它多产生的附加贡献是多少,以及当第二个滑动窗口将要离开 ( l , r ) (l,r) (l,r)的时候,对它的附加贡献又会减少多少,体现在差分数组上就是某些位置的加减关系。差分数组被预处理好了之后,扫一遍差分数组相当于就是模拟第二个滑动窗口的扫动过程,再此过程中计算前缀和并加到附加贡献上即可,同时还要不断跟答案取max。

int n,m,k,al[maxn],ar[maxn],val[maxn];
 
 
int main(){
	n=rd(),m=rd(),k=rd();
	FOR(i,0,m)al[i]=rd(),ar[i]=rd();
	int ans=0;
	FOR(i,k,n+1){
		int as=0,L=i-k+1,R=i;
		FOR(j,0,m){
			int l=al[j],r=ar[j],tt=0;
			as+=(tt=max(min(r,R)-max(L,l)+1,0));
			if(min(r-l+1,k)>tt){
				val[l+tt]++;
				val[min(l+k,r+1)]--;
				val[max(r+1,l+k)]--;
				val[r-tt+1+k]++;
			}
		}
		int pre=0;
		FOR(j,1,n+1){
			pre+=val[j];
			as+=pre;
			ans=max(ans,as);
			val[j]=0;
		}
	}
	wrn(ans);
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值