#保序回归问题,单调栈,二分#洛谷 5294 [HNOI2019]序列
题目
给定一个长度为 \(n\) 的序列 \(A\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k\)。
第一次修改之前及每次修改之后,都要求你找到一个同样长度为 \(n\) 的单调不降序列 \(B\),
使得 \(\sum_{i=1}^n(A_i-B_i)^2\) 最小,并输出最小值。
需要注意的是每次操作的影响都是独立的,也即每次操作只会对当前询问造成影响。
\(n\leq 10^5,A\leq 10^9\)
分析
对于形如最小化 \(\sum C_i(A_i-m)^2\) 的问题,\(m\) 应取 \(\large \frac{\sum C_iA_i}{\sum C_i}\)
而且这个序列 \(B\) 等同于用单调递增的 \(m\) 去覆盖,这种问题可以用单调栈维护均值。
考虑比较独立的修改可以离线做,此时 \([1,x)\) 和 \((x,n]\) 的单调栈都可以求出来。
反向的单调栈原理相同,先倒着做一遍再把出入栈撤销。
修改的位置会修改中间一段,两边依旧是原来的单调栈,
所以可以二分右端点,其位置越靠前,答案越小;
当右端点二分的情况下,再二分左端点,其位置越靠后答案越小。
时间复杂度 \(O(n\log ^2 n)\)
代码
#include <cstdio>
#include <cctype>
#include <stack>
#define rr register
using namespace std;
const int N=100011,mod=998244353;
typedef long long lll; lll s[N];
struct node{int y,next;}q[N]; stack<int>K[N];
int wl[N],wr[N],a[N],_s[N],n,Q,as[N],Tol,Tor,stal[N],star[N],ans[N];
inline signed iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline signed o(int x){return 1ll*x*x%mod;}
inline signed ksm(int x,int y){
rr int ans=1;
for (;y;y>>=1,x=1ll*x*x%mod)
if (y&1) ans=1ll*ans*x%mod;
return ans;
}
struct rec{
lll x; int y;
inline bool operator <=(const rec &t)const{
return (double)x*t.y<=(double)t.x*y;
}
inline signed ans(){return 1ll*o(x%mod)*ksm(y,mod-2)%mod;}
}cl[N],cr[N];
inline rec slope(int l,int r){return (rec){s[r]-s[l-1],r-l+1};}
inline signed Get(int x,int now){
rr int l=0,r=Tol;
while (l<r){
rr int mid=(l+r+1)>>1;
if (cl[mid]<=(rec){s[x-1]-s[stal[mid]]+now,x-1-stal[mid]}) l=mid;
else r=mid-1;
}
return l;
}
inline signed query(int now){
rr int l=0,r=Tor,mid,_l;
while (l<r){
_l=Get(star[mid=(l+r+1)>>1],now);
if ((rec){s[star[mid]-1]-s[stal[_l]]+now,star[mid]-1-stal[_l]}<=cr[mid]) l=mid;
else r=mid-1;
}
_l=Get(star[r],now);
return mo(mo(wl[_l],wr[r]),(rec){s[star[r]-1]-s[stal[_l]]+now,star[r]-stal[_l]-1}.ans());
}
signed main(){
n=iut(),Q=iut(),star[0]=n+1;
for (rr int i=1;i<=n;++i) s[i]=s[i-1]+(a[i]=iut());
for (rr int i=1;i<=n;++i) _s[i]=mo(_s[i-1],o(a[i]));
for (rr int i=1;i<=Q;++i){
rr int x=iut(),y=iut();
q[i]=(node){y-a[x],as[x]},as[x]=i;
}
for (rr int i=n;i;--i){
for (;Tor&&cr[Tor]<=slope(i,star[Tor]-1);K[i].push(star[Tor--]));
star[++Tor]=i,wr[Tor]=mo(wr[Tor-1],(cr[Tor]=slope(i,star[Tor-1]-1)).ans());
}
print(mo(_s[n],mod-wr[Tor]));
for (rr int i=1;i<=n;++i){
--Tor;
for (;!K[i].empty();K[i].pop())
star[++Tor]=K[i].top(),wr[Tor]=mo(wr[Tor-1],(cr[Tor]=slope(star[Tor],star[Tor-1]-1)).ans());
rr int now=mo(_s[n],mod-o(a[i]));
for (rr int j=as[i];j;j=q[j].next)
ans[j]=mo(now,mo(o(a[i]+q[j].y),mod-query(q[j].y)));
for (;Tol&&slope(stal[Tol]+1,i)<=cl[Tol];--Tol);
stal[++Tol]=i,wl[Tol]=mo(wl[Tol-1],(cl[Tol]=slope(stal[Tol-1]+1,i)).ans());
}
for (rr int i=1;i<=Q;++i) putchar(10),print(ans[i]);
return 0;
}
#保序回归问题,单调栈,二分#洛谷 5294 [HNOI2019]序列的更多相关文章
- 洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找)
洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1333275 这个题不是很 ...
- BZOJ1012最大数 [JSOI2008] 单调栈+二分
正解:单调栈+二分查找(or,线段树? 解题报告: 拿的洛谷的链接quq 今天尝试学习了下单调栈,然后就看到有个博客安利了这个经典例题?于是就去做了,感觉还是帮助了理解趴quqqqqq 这题,首先,一 ...
- 103 保序回归 isotonic regression
103 保序回归 isotonic regression 2016-03-30 11:25:27 bea_tree 阅读数 6895 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权 ...
- BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]
1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 8748 Solved: 3835[Submi ...
- scikit-learn一般实例之一:保序回归(Isotonic Regression)
对生成的数据进行保序回归的一个实例.保序回归能在训练数据上发现一个非递减逼近函数的同时最小化均方误差.这样的模型的好处是,它不用假设任何形式的目标函数,(如线性).为了比较,这里用一个线性回归作为参照 ...
- 机器学习:保序回归(IsotonicRegression):一种可以使资源利用率最大化的算法
1.数学定义 保序回归是回归算法的一种,基本思想是:给定一个有限的实数集合,训练一个模型来最小化下列方程: 并且满足下列约束条件: 2.算法过程说明 从该序列的首元素往后观察,一旦出现乱序现象停止该轮 ...
- Spark机器学习(3):保序回归算法
保序回归即给定了一个无序的数字序列,通过修改其中元素的值,得到一个非递减的数字序列,要求是使得误差(预测值和实际值差的平方)最小.比如在动物身上实验某种药物,使用了不同的剂量,按理说剂量越大,有效的比 ...
- bzoj 4709 [Jsoi2011]柠檬——单调栈二分处理决策单调性
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4709 题解:https://blog.csdn.net/neither_nor/articl ...
- Spark Mllib里如何采用保序回归做回归分析(图文详解)
不多说,直接上干货! 相比于决策树,保序回归的应用范围没有决策树算法那么广泛. 特别在数据处理较为庞大的时候,采用保序回归做回归分析,可以极大地节省资源,从而提高计算效率. 保序回归的思想,是对数据进 ...
- 51NOD 1962 区间计数 单调栈+二分 / 线段树+扫描线
区间计数 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80 两个数列 {An} , {Bn} ,请求出Ans, Ans定义如下: Ans:=Σni=1Σnj=i[max{ ...
随机推荐
- 用random.simple来解决从0-99这100个数中随机取10个不重复的数
语法: random.simple(list,k) 返回以长度为k的新列表,新列表存放list所产生k个随机不重复的元素 import random print(random.simple(range ...
- git 多系统复用账号
重装系统前请备份~/.ssh下的公钥私钥文件,重装系统后,请使用以下方法复用好之前的key 将备份好的key copy至~/.ssh下 将私钥id_rsa的文件属性改为600:sudo chmod 6 ...
- 面试官:说一下红锁RedLock的实现原理?
RedLock 是一种分布式锁的实现算法,由 Redis 的作者 Salvatore Sanfilippo(也称为 Antirez)提出,主要用于解决在分布式系统中实现可靠锁的问题.在 Redis 单 ...
- [C++逆向] 6 函数的工作原理
目录 栈帧的形成和关闭 各种调用方式的考察 _stdcall _cdecl _fastcall 使用ebp或者esp寻址 某次调用函数时的栈结构 函数参数 不定长参数 函数的返回值 栈帧的形成和关闭 ...
- RocketMQ(6) offset管理
这里的offset指的是Consumer的消费进度offset. 消费进度offset是用来记录每个Queue的不同消费组的消费进度的.根据消费进度记录器的不同,可以分为两种模式:本地模式和远程模式. ...
- 深入理解与应用CSS clip-path 属性
clip-path clip-path是什么 clip-path 是一个CSS属性,允许开发者创建一个剪切区域,从而决定元素的哪些部分可见,哪些部分会被隐藏.通过定义这个剪切路径(clipping p ...
- ThreadLocal父子间通信的四种解决方案
ThreadLocal父子间通信的四种解决方案 ThreadLocal 是存储在线程栈帧中的一块数据存储区域,其可以做到线程与线程之间的读写隔离. 但是在我们的日常场景中,经常会出现父线程需要向子线程 ...
- Redis稳定性之战:AOF日志支撑数据持久化
★ Redis24篇集合 1 介绍 AOF(Append Only File)持久化:以独立日志的方式存储了 Redis 服务器的顺序指令序列,并只记录对内存进行修改的指令. 当Redis服务发生雪崩 ...
- python中bytes转int的实例(bytearray to short int in python)
python很多数据都是bytes格式的,经常需要转换成int或者short,笔者实际项目有需求,这里就做个笔记吧. 实例一: bytes转short:(无符号类型) import struct ba ...
- linux系统运行时参数命令、网络、磁盘参数和日志监控
重点内容 linux基础命令和工具 CPU性能监控 内存性能监控 文件IO性能监控 网络IO监控 1 linux基础命令和工具 1.1 Grep搜索字符 grep命令用于在文件中执行关键字搜索,并显示 ...