首页 > 其他分享 >EI 的区间加正数区间最大子段和的 polylog 做法(KTT)

EI 的区间加正数区间最大子段和的 polylog 做法(KTT)

时间:2023-10-04 17:34:10浏览次数:40  
标签:lmx EI 子段 int rmx sl 区间 Line sg

非常有道理。orz EI。

首先单点修改区间最大子段和是 GSS 的经典问题。我们维护出区间和 \(sm\)、最大前缀和 \(lmx\)、最大后缀和 \(rmx\)、最大子段和 \(mx\),发现这是一种半群信息,直接线段树维护就可以了。

那么对于区间加正数问题,我们依然考虑线段树。线段树想要 pushdown 标记就得先考虑全局加正数。

发现全局加了一个正数后,无论前后缀和最大子段和都倾向于扩大选中的区间长度,这也就表明了假设我们对一个数列不断的全局 +x,那么 \(mx,lmx,rmx\) 关于 \(x\) 都是一个下凸的分段线性函数。这启发我们直接对每一个区间维护一个一次函数。即,对于每一个区间的 \(lmx,rmx,mx\) 我们记录当前状态下它代表的下凸壳上的点所在的那条直线。

我们同时再维护一个 \(lim\) 表示当前区间 \(+lim\) 后,它子树中会存在一个区间的所在直线发生变化。这个信息是很好维护的,我们只需要注意到所有信息的转移都形如取在常数个一次函数中取截距最大的那条转移。那么我们只需要在不是最大的那些函数中与取到了最大值的函数求个交点,然后取交点横坐标最小值就可以了。因为选取的一次函数发生改变当且仅当一条截距小但是斜率大的线“后来居上”。

维护了这些信息后,当我们遇到一个区间加上一数后 \(>lim\) 的情况就暴力往下递归打标记。查询直接按 GSS 的方式查。

这个算法的复杂度证明其实也没有想象中的那么困难。发现我们保持复杂度。下去打球。

#include <cstdio>
#include <algorithm>
#define lc (p<<1)
#define rc (p<<1|1)
using namespace std;
int read(){
	char c=getchar();int x=0;bool f=0;
	while(c<48||c>57) f|=(c=='-'),c=getchar();
	do x=(x<<1)+(x<<3)+(c^48),c=getchar();
	while(c>=48&&c<=57);
	if(f) return -x;
	return x;
}
const int N=400003;
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n,q;
ll a[N];
void chmn(ll &x,ll v){if(x>v) x=v;}
struct Line{
	int k;ll b;
	Line(int K=0,ll B=0):k(K),b(B){}
	friend Line operator+(const Line x,const Line y){return Line(x.k+y.k,x.b+y.b);}
	friend Line opt(const Line x,const Line y,ll &cur){
		if(x.b==y.b){
			if(x.k>y.k) return x;
			else return y;
		}
		if(x.b>y.b){
			if(x.k<y.k) chmn(cur,(x.b-y.b)/(y.k-x.k));
			return x;
		}
		else{
			if(x.k>y.k) chmn(cur,(y.b-x.b)/(x.k-y.k));
			return y;
		}
	}
};
struct Info{
	Line sm,lmx,rmx,mx;ll lim;
	Info(Line S=Line(),Line L=Line(),Line R=Line(),Line M=Line(),ll Lim=INF):sm(S),lmx(L),rmx(R),mx(M),lim(Lim){}
	friend Info operator+(const Info x,const Info y){
		ll clim=INF;
		Info res(x.sm+y.sm,opt(x.sm+y.lmx,x.lmx,clim),opt(y.sm+x.rmx,y.rmx,clim),opt(opt(x.mx,y.mx,clim),x.rmx+y.lmx,clim),min(x.lim,y.lim));
		chmn(res.lim,clim);
		return res;
	}
}sg[N<<2];
ll tg[N<<2];
int loc[N<<2];
void init(int p){
	int x=loc[p];
	Line cur(1,a[x]);
	if(a[x]<0) sg[p]=Info(cur,Line(),Line(),Line(),-a[x]);
	else sg[p]=Info(cur,cur,cur,cur,INF);
}
void build(int p=1,int l=1,int r=n){
	if(l==r){loc[p]=l;return init(p);}
	int mid=(l+r)>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	sg[p]=sg[lc]+sg[rc];
}
void proc(int p,ll v){
	if(loc[p]) a[loc[p]]+=v;
	tg[p]+=v;
	sg[p].sm.b+=sg[p].sm.k*v;
	sg[p].lmx.b+=sg[p].lmx.k*v;
	sg[p].rmx.b+=sg[p].rmx.k*v;
	sg[p].mx.b+=sg[p].mx.k*v;
	sg[p].lim-=v;
}
void pushdown(int p){
	if(tg[p]){
		proc(lc,tg[p]);
		proc(rc,tg[p]);
		tg[p]=0;
	}
}
void update(int sl,int sr,int v,int p=1,int l=1,int r=n){
	if(loc[p]){a[loc[p]]+=v;return init(p);}
	pushdown(p);
	int mid=(l+r)>>1;
	if(sl<=l&&r<=sr){
		if(sg[p].lim>=v) return proc(p,v);
		update(sl,sr,v,lc,l,mid);
		update(sl,sr,v,rc,mid+1,r);
	}
	else{
		if(sl<=mid) update(sl,sr,v,lc,l,mid);
		if(sr>mid) update(sl,sr,v,rc,mid+1,r);
	}
	sg[p]=sg[lc]+sg[rc];
}
Info query(int sl,int sr,int p=1,int l=1,int r=n){
	if(sl<=l&&r<=sr) return sg[p];
	pushdown(p);
	int mid=(l+r)>>1;
	if(sr<=mid) return query(sl,sr,lc,l,mid);
	if(sl>mid) return query(sl,sr,rc,mid+1,r);
	return query(sl,sr,lc,l,mid)+query(sl,sr,rc,mid+1,r);
}
int main(){
	n=read();q=read();
	for(int i=1;i<=n;++i) a[i]=read();
	build();
	while(q--){
		char c=getchar();
		while(c!='A'&&c!='Q') c=getchar();
		int l=read(),r=read();
		if(c=='A') update(l,r,read());
		if(c=='Q') printf("%lld\n",query(l,r).mx.b);
	}
	return 0;
}

标签:lmx,EI,子段,int,rmx,sl,区间,Line,sg
From: https://www.cnblogs.com/yyyyxh/p/17742485.html

相关文章

  • 遥遥领先!BEVHeight++:针对路侧视觉3D目标检测新方案!
    前言 回归到地面的高度,以实现距离不可知的公式,从而简化仅相机感知方法的优化过程。在路侧camera的3D检测基准上,方法大大超过了以前所有以视觉为中心的方法。它比BEVDepth产生了+1.9%的NDS和+1.1%的mAP的显著改善。在nuScenes测试集上,方法取得了实质性的进步,NDS和mAP分别增加了+2.......
  • Codeforces 1874F - Jellyfish and OEIS
    考虑对\(\summ_i-i+1\)个不可行的集合进行容斥,即钦定一些区间集,要求它们对应的\(p_l,p_{l+1},\cdots,p_r\)必须是\([l,r]\)的排列,计算方案数乘以容斥系数之和。如果容斥的集合中存在相交的区间,那么这个方案数其实不太好计算。不过根据区间的性质,对于\(l_1<l_2\ler_1<r_2......
  • csps区间dp
    加分二叉树我们可以枚举中间这个k的位置,然后分别递归计算左右子树,这就让我们想到这是一个和区间有关的,我们可以用区间dp来解决。\(f[i][j]\)表示i,j这个区间的最大分值。用一个很板子的区间dp就可以解决了。至于求前序遍历,我们也只需要通过递归然后枚举中间的根,第一个满足......
  • Oracle数据库升级PostgreSQL 后的踩坑记录(一)之databaseId
    背景:因为业务需求,需要整个项目除了适配oracle和mysql后还需要适配PostgreSQL,在此背景下就出现了一系列的问题。踩坑一:databaseId连接数据库后启动发现某些查询报错传入的sql参数是空,经过反复排查定位到对应的MyBaits的xml文件,我贴出原始的文件文件中判断databaseid是mysql还是oracl......
  • 2022 China Collegiate Programming Contest (CCPC) Weihai Site
    PrefaceVP到自己学校出的题了可海星,不得不说学长们出的题比起昨天VP的CCPC2022广州做起来要舒服地多这场前面写题都很顺基本都是一发过,中期的medium也没怎么卡思路和卡机子,一道一道地慢慢出最后一个小时徐神RushF可惜没Rush出来,然后我和祁神坐在下面把B的做法给搞出来了,但不知......
  • 基础算法:区间合并
    1、区间合并以AcWing.803为例,题目要求如下:给定n个区间[li,ri],要求合并所有有交集的区间。注意如果在端点处相交,也算有交集。输出合并完成后的区间个数。例如:[1,3]和[2,6]可以合并为一个区间[1,6]。输入格式第一行包含整数n。接下来n行,每行包含两个整数l和r。输......
  • SpringCloud微服务学习笔记(二)【Feign,Gateway,Docker】
    Feign先来看我们以前利用RestTemplate发起远程调用的代码:存在下面的问题:•代码可读性差,编程体验不统一•参数复杂URL难以维护Feign是一个声明式的http客户端,官方地址:https://github.com/OpenFeign/feign其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。基......
  • Keil 配置bin文件
    1、在User中勾选build,在命令中添加下面 D:\SoftWare\Keil_v5\ARM\ARMCLANG\bin\fromelf.exe--bin--outputD:\code\Fwlib-Template\Project\Objects\BH-F103.binD:\code\Fwlib-Template\Project\Objects\BH-F103.axf这里的bin文件名在Output中修改然后在重新编译一下就......
  • Pink Noise Is All You Need: Colored Noise Exploration in Deep Reinforcement Lear
    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布!PublishedasaconferencepaperatICLR2023 ABSTRACT 1INTRODUCTION 2BACKGROUND&RELATEDWORK 3METHOD 4ISPINKNOISEALLYOUNEED? 4.1DOESTHENOISETYPEMATTER? 4.2ISPINKNOISE......
  • 旅游党必备!带上搭载HarmonyOS 4的HUAWEI Mate 60系列轻松出游!
    不知不觉中秋十一小长假如期而至,时长8天的假期,许多小伙伴或许早已制定好出行计划,订酒店、订机票、查询当地天气等都已经准备起来了。既然要带上各种装备,不如将其他繁琐的流程交给华为手机,我们只管尽情享受沿途风景,享受美好的十一黄金假期。  任务进度随时掌握,重要信息始终在线......