【loj3059】【hnoi2019】序列
题目
给出一个长度为 \(n\) 的序列 \(A\) ;
你需要构造一个新的序列\(B\) ,满足:
- $B_{i} \le B_{i+1} (1 \le i \lt n ) $
- $\sum_{i=1}^{n} (A_i - B_i)^2 $ 最小
题解
出题人和题解在这里 : http://15283746.blog.uoj.ac/blog/4966
我只是整理了一下证明(Part 1)并套了一种做法(Part 2);
Part 1
主要讨论最优的策略:
引理一:
如果要求所有\(B_i\)相同等于\(x\),那么$x \ = \ \frac{\sum_{i=1}^{n} A_i }{n} $
证明:写成关于\(x\)的二次函数即可证明;
定理一:
答案一定是很多严格上升的等值段,即每一段的\(B\)相同,且等于这段\(A\)的平均值\(v(A)\) ;
证明:由于相邻等值块的值严格不同,根据二次函数的性质,一定可以向靠近平均值的方向调整;
引理二:
将任意一个序列延长之后,原序列对延长后的序列答案的贡献不小于原序列的最优答案;
证明:由于是最优的所以显然,否则矛盾;
引理三:
等值段的划分唯一;
证明:
( - _ -) 建立线性规划模型, $B_i \le B_{i+1} $ 这个不等式组在空间中的解是一个凸集,最优的点相当于和圆\((A_1,A_2,...,)\)的切点,感受一下可以知道是唯一的;
定理二:
下列构造方法是最优的:
维护一个以平均值为权值的单调栈,当加入一个点时,如果不满足单调性,则合并栈尾和当前区间,重复这个过程,最后将区间加入单调栈;证明:
最优的划分为\(H[x,y]\) ,令如上策略的划分为\(H'[x,y]\) ,考虑归纳;
假设对\(1 \le i \lt n\)均满足\(H=H'\) ,当\(i=n\)时:
1.如果\(H'\)中含有两个及以上个等值块,可以划分两个长度<n的区间分别构造\(H_1'\)和\(H_2'\);
根据引理二,可以知道一定是最优的;
由构造方式这两个区间一定可以直接拼接且$H' = H_1' + H_2' $;
2.如果\(H'\)中只有一个等值块,只需要证明任意大于1个等值块的\(H\)都不优即可;
假设\(i\)是划分\(H\)的最后一个满足\(i\)和\(i+1\)不同块的点;
考虑\(H'[1,i]\),设\(i\)在的块是\([j,i]\),在\(i+1\)到\(n\)之间一定存在第一个\(k\)合并了\([ j,i ]\)和\([i+1,k]\) ;
由于$v[j,i] \lt v[i+1,n] \ , \ v[j,i] \ge v[i+1,k] $ ;
所以$v[k+1,n] \gt v[j,i] \ge v[i+1,k] $ ;
所以\(H'[1,k] + H'[k+1,n]\)一定合法且比\(H\)优;
至此在不修改的时候可以 \(O(n)\) 解决问题;
Part 2
考虑如何合并\([1,i-1 ]\)和\([i,i]\)和\([i+1,n]\),先讨论合并两个区间的情况;
定理三:
两个区间的并的划分方案中任意一个划分点在子区间中也一定是划分点;
从左到右执行,一定不会使左区间的划分点变多,从右往左同理,根据引理三得证,可以推广到多个区间的情况;
根据引理三,设两个区间为\([1,mid]\)和\([mid+1,n]\),可以先处理出\(H'[1,mid-1]\)和\(H'[mid+1,n]\),根据定理三,为了方便修改意义区间元素直接是等值块,最终被合并的一定是左区间的一段后缀+右区间的一段前缀,令其为区间\([L_0,R_0]\),\(v[L_0,R_0]\) 表示区间平均值;
引理四:
当加入到右区间的$ R \(时,设\) L_0 $是此时合并到的左端点,则:
1.合法条件为:$v[L_0,R] \gt v_{L0-1} $ ,且具有可二分性;
2.\(L_0\)是使得\(v[L,R]\)最大的\(L\);
证明:
由于栈是单增的并且在合并过程中,加入点的权值的变化是单调不增的,所以12得证;
定理四:
对于右边的一个等值块\(R\),\(L\)是其在引理四中的\(L_0\),若:
1.\(R<R_0\) 则有\(v[L,R] \ge v_{R+1}\) ;2.\(R \ge R_0\) 则有\(v[L,R] \lt v_{R+1}\) ;
证明:
由于\(R_0\)一定满足2,只需要证明对于一个满足的\(R\),\(>R\)的位置一定满足2即可;
归纳假设\(R\)满足,左端点设为\(L\),对于\(R+1\),左端点设为\(L'\),有引理四2和假设得到:\(v[L',R] \le v[L,R] \lt v_{R+1}\),所以$v[L',R+1] \lt v_{R+1} \lt v_{R+2} $ ,得证;
引理四和定理四在中间有一个修改点 \(i\) 的时候依旧适用;
所以可以找出[1,i-1]的单调和[i+1,n]的单调栈(从n做到1再往后退栈),二分套二分即可;
#include<bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
const int N=100010;
int n,m,ny[N],pl,pr,len[N],ansl[N],ansr[N],pre[N],ql,qr,ans[N];
struct query{
int x,y,id;
query(int _x=0,int _y=0,int _id=0):x(_x),y(_y),id(_id){};
bool operator <(const query&A)const{return x<A.x;}
}Q[N];
struct data{
ll x,y,z;
data(ll _x=0,ll _y=0,ll _z=0):x(_x),y(_y),z(_z){};
data operator +(const data&A)const{return data(x+A.x,y+A.y,z+A.z);}
data operator -(const data&A)const{return data(x-A.x,y-A.y,z-A.z);}
bool operator <=(const data&A)const{return y*A.x<=A.y*x;}
bool operator >=(const data&A)const{return y*A.x>=A.y*x;}
}A[N],L[N],R[N],pR[N],sL[N],sR[N],psR[N],X,Y,Z;
data getL(int l,int r){return sL[r]-sL[l-1];}
data getR(int l,int r){return sR[r]-sR[l-1];}
int cal(data now){
int x=now.x,y=now.y%mod,z=now.z%mod;
int v=(ll)y*ny[x]%mod;
return (z-(ll)v*y*2%mod+(ll)v*v%mod*x%mod+mod)%mod;
}
void lowerL(){
int l=1,r=pl+1;
while(l<r){
int mid=(l+r+1)>>1;
Z=Y+getL(mid,pl);
if(Z<=L[mid-1])r=mid-1;
else l=mid;
}
Z=Y+getL(ql=l,pl);
}
void lowerR(){
int l=1,r=pr+1;
while(l<r){
int mid=(l+r+1)>>1;
Y=X+getR(mid,pr);
lowerL();
if(Z>=R[mid-1])r=mid-1;
else l=mid;
}
Y=X+getR(qr=r,pr);
lowerL();
}
int main(){
// freopen("sequence.in","r",stdin);
// freopen("sequence.out","w",stdout);
scanf("%d%d",&n,&m);ny[1]=1;
for(int i=2;i<=n;++i){ny[i]=1ll*(mod-mod/i)*ny[mod%i]%mod;}
for(int i=1;i<=n;++i){
int x;scanf("%d",&x);
A[i]=data(1,x,(ll)x*x%mod);
}
for(int i=1;i<=m;++i){
int x,y;scanf("%d%d",&x,&y);
Q[i]=query(x,y,i);
}
sort(Q+1,Q+m+1);
L[0]=data(1,0,0);
R[0]=data(1,1e9+1,0);
for(int i=n;~i;--i){
data now=A[i];
while(now>=R[pr])now=now+R[pr--];
len[i]=++pr;
pR[i]=R[pr];R[pr]=now;
psR[i]=sR[pr];sR[pr]=sR[pr-1]+now;
pre[i]=ansr[pr];ansr[pr]=(ansr[pr-1]+cal(now))%mod;
}
ans[0]=ansr[pr];
for(int i=1,tl=0,tr=1;i<=m;++i){
while(tr<Q[i].x+1){
R[pr]=pR[tr];
sR[pr]=psR[tr];
ansr[pr]=pre[tr];
pr=len[++tr];
}
while(tl<Q[i].x-1){
data now=A[++tl];
while(now<=L[pl])now=L[pl--]+now;
L[++pl]=now;
sL[pl]=sL[pl-1]+now;
ansl[pl]=(ansl[pl-1]+cal(now))%mod;
}
X=data(1,Q[i].y,(ll)Q[i].y*Q[i].y%mod);
lowerR();
ans[ Q[i].id ] = ((ll)ansl[ql-1] + ansr[qr-1] + cal(Z)) %mod;
}
for(int i=0;i<=m;++i)printf("%d\n",ans[i]);
return 0;
}
【loj3059】【hnoi2019】序列的更多相关文章
- 【洛谷5294】[HNOI2019] 序列(主席树维护单调栈+二分)
点此看题面 大致题意: 给你一个长度为\(n\)的序列\(A\),每次询问修改一个元素(只对当前询问有效),然后让你找到一个不下降序列\(B\),使得这两个序列相应位置之差的平方和最小,并输出这个最小 ...
- 【题解】Luogu P5294 [HNOI2019]序列
原题传送门 题意:给你一个长度为\(n\)的序列\(A\),每次询问修改一个元素(只对当前询问有效),然后让你找到一个不下降序列\(B\),使得这两个序列相应位置之差的平方和最小,并输出这个最小平方和 ...
- 【Luogu5294】[HNOI2019]序列
题目链接 题意 给定一个序列,要求将它改造成一个非降序列,修改一个数的代价为其改变量的平方. 最小化总代价. 另有\(Q\) 次询问,每次修改一个位置上的数.(询问之间独立,互不影响) Sol 神仙 ...
- [HNOI2019]序列(单调栈+二分)
通过打表证明发现答案就是把序列划分成若干段,每段的b都是这一段a的平均数.50分做法比较显然,就是单调栈维护,每次将新元素当成一个区间插入末尾,若b值不满足单调不降,则将这个区间与单调栈前一个区间合并 ...
- 题解 [HNOI2019]序列
题目传送门 题目大意 给出一个\(n\)个数的数列\(A_{1,2,...,n}\),求出一个单调不减的数列\(B_{1,2,...,n}\),使得\(\sum_{i=1}^{n}(A_i-B_i)^ ...
- luogu P5294 [HNOI2019]序列
传送门 这个什么鬼证明直接看uoj的题解吧根本不会证明 首先方案一定是若干段等值的\(B\),然后对于一段,\(B\)的值应该是\(A\)的平均值.这个最优方案是可以线性构造的,也就是维护以区间平均值 ...
- CSP-S2019「Symphony」
NOTICE:如觉得本文有什么错误或不妥之处,欢迎评论区以及私信交流,反对乱喷,如有一些让人不爽的评论或人身攻击,带来的后果本人一律不负责 准备工作 Day-inf~Day-3 000 every d ...
- Loj #3059. 「HNOI2019」序列
Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...
- LOJ 3059 「HNOI2019」序列——贪心与前后缀的思路+线段树上二分
题目:https://loj.ac/problem/3059 一段 A 选一个 B 的话, B 是这段 A 的平均值.因为 \( \sum (A_i-B)^2 = \sum A_i^2 - 2*B \ ...
随机推荐
- Github下载慢和下载过程中断等情况的解决方案
Github下载慢和下载过程中断等情况的解决方案 最近老大push项目,正常的git clone每次都是下载一部分就断掉了. 尝试了修改hosts文件的方式,更换了延迟最低的域名也没啥用(难道我姿 ...
- 【开发笔记】- 发送邮件(通过JavaMail发送)
前段时间在工作中用到了邮件发送监控的报警信息,今天在这个记录一下JavaMail的邮件工具类. 下边为用到的JavaMail的jar包的pom依赖.这里用的是JavaMail的1.4.6的版本. &l ...
- 【转】Vue.js——60分钟组件快速入门(上篇)
文章作者:keepfool 文章出处:http://www.cnblogs.com/keepfool/ 组件简介 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的 ...
- 京信通信成功打造自动化工厂(MES应用案例)
企业介绍: 京信通信成立于1997年,是一家集研发.生产.销售及服务于一体的移动通信外围设备专业厂商,致力于为客户提供无线覆盖和传输的整体解决方案,于2003年在香港联交所主板上市(2342.HK), ...
- Git管理修正(取消跟踪、合并commit)
本文总结了最近使用Git时候遇到的两个问题: 1. 当将不必要跟踪的文件加入到仓库后如何处理? 2. 提交了多个功能相同的commit后如何处理? 总结经验 在创建仓库的一开始,就要设置号.gitig ...
- suoermap的object.net循环遍历属性表,从数据库取数据进行更新属性字段值
/// </summary> /// <param name="sName">图层名</param> /// <param name=&q ...
- windows安装redis服务
下载地址: https://github.com/microsoftarchive/redis/releases 解压. git执行:
- JavaScript 解决 url 中的中文乱码问题
页面传值过程中,通过 url 传值,发现中文会乱码. 以下是解决方法: 1.传的页面: encodeURI(url + "?userName=" + userName); //en ...
- Java-最常用的Java日志框架整理
Java-最常用的Java日志框架整理 前言 Java程序员,我们开发了很多Java应用程序,包括桌面应用.WEB应用以及移动应用.然而日志系统是一个成熟Java应用所必不可少的,在开发和调试阶段,日 ...
- 【笔记】MAML-模型无关元学习算法
目录 论文信息: Finn C, Abbeel P, Levine S. Model-agnostic meta-learning for fast adaptation of deep networ ...