#保序回归问题,单调栈,二分#洛谷 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{ ...
随机推荐
- redis7源码分析:redis 启动流程
1. redis 由 server.c 的main函数启动 int main(int argc, char **argv) { ... // 上面的部分为读取配置和启动命令参数解析,看到这一行下面为启 ...
- 项目实战:Qt编译Qt库以及使用C#调用Qt库,并实现C#集成Qt的tcp客户端
需求 1.Qt已经开发了应用,封装成Qt库,以供C#调用. 2.Qt的tcp客户端封装,以供C#调用,双向传递数据. 原理 1.使用QtCreator编译msvc版本的Qt库: 2.使 ...
- 6大数据类型之间的转换及数据在内存中的缓存机制----day03
1.自动类型转换 当2个不同类型的数据进行运算的时候,默认向更高精度转换 数据类型精度从低到高:bool < int < float <complex 1,1强制类型转换 # Nu ...
- queryset高级用法:prefetch_related
这个方法和select_related方法类型,就是访问多个表中的数据的时候,减少查询的次数.这个方法是为了解决一对多和多对多的关系的查询问题.比如要获取标题中带有hello字符串的文章以及它的所有标 ...
- 亲测可行,Android Studio 查看源码出现 Source for ‘Android API xxx Platform’ not found 的解决方法
亲测可行,Android Studio 查看源码出现 Source for 'Android API xxx Platform' not found 的解决方法 如标题中的问题,产生的原因就是 SDK ...
- jquery实现轮播图切换
这个是我模仿网易云的音乐界面写的轮播图,主要实现的功能有 1.每隔4秒图片和对应的背景颜色一起切换 2.点击翻页会跳转到相对应的图片以及背景上 3.点击左右翻页,实现顺序切换 <1>HTM ...
- 【认知服务 Azure Cognitive Service】使用Azure Search中Create an Demo的示例时,出现空白页面的问题
问题描述 在根据Azure 认知服务的Search功能文档创建示例时(快速入门:在门户中创建演示应用(Azure 认知搜索)).完全相同的步骤,在中国区创建后下载Demo,查询结果一片空白:如下: 而 ...
- 【Azure 应用服务】如何禁止chinacloudsites.cn 访问?
问题描述 Azure App Service创建后,默认会有一个 Azure App Service创建后,默认会有一个 https://xxxxxxxxxxxxx.chinacloudsites. ...
- ASP.NET Core 选项
目录 1,选项接口 2,注入配置与IOptions 3,IOptionsSnapshot 首先要了解 ASP.NET Core 中的配置,请点击这里了解:https://www.cnblogs.com ...
- 云原生 on nLive:云上 Nebula Graph
本文首发于 Nebula Graph Community 公众号 在 #云原生# 主题分享中,来自 Nebula 云组的 Cloud 专家乔雷同大家分享云的相关知识,本文整理自该次主题直播. 云原生是 ...