luogu P5294 [HNOI2019]序列
这个什么鬼证明直接看uoj的题解吧根本不会证明
首先方案一定是若干段等值的\(B\),然后对于一段,\(B\)的值应该是\(A\)的平均值.这个最优方案是可以线性构造的,也就是维护以区间平均值为权值的单调栈,每次在后面插入一个元素,不断弹栈并与最后一个合并,直到平均值单调递增
然后这个单调栈是可以两个区间的单调栈直接合并的,因为合并完后新单调栈的断点集合是原来两段的断点集合的子集.合并直接暴力就好了合并的话一定是前面那个的一段后缀的后面的一段前缀合并,然后后面的前缀位置(就是合并区间的右端点)是可以二分的,然后二分左端点使得合并的区间平均值最大,然后如果这个平均值比右端点右边的那一块的平均值小,那么最优的右端点就在在这个右端点以及其左边,否则在右边
然后用个可持久化线段树预处理一下每个前缀和后缀的单调栈就行了,注意从后往前和从前往后做都是一样的,能得到最优解
以上都是蒯的题解qwq,感性理解一下?
// luogu-judger-enable-o2
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db long double
using namespace std;
const int N=1e5+10,mod=998244353;
const db eps=1e-10;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;} return an;}
int inv(int a){return fpow(a,mod-2);}
LL sm[N*85],rsm[N*85];
int n,m,st[N],tp,a[N],ps1[N],ps2[N],an[N*85],nm[N*85],rnm[N*85],ch[N*85][2],len1[N],len2[N],rt1[N],rt2[N],tt;
LL sta[N][2];
void inst(int o1,int o2,int x,int ll,int rr,LL ns,int nn)
{
int l=1,r=n,tl=0;
while(l<r)
{
st[++tl]=o1;
int mid=(l+r)>>1;
if(x<=mid)
{
ch[o1][0]=++tt,ch[o1][1]=ch[o2][1];
o1=ch[o1][0],o2=ch[o2][0];
r=mid;
}
else
{
ch[o1][0]=ch[o2][0],ch[o1][1]=++tt;
o1=ch[o1][1],o2=ch[o2][1];
l=mid+1;
}
}
sm[o1]=rsm[o1]=ns,nm[o1]=rnm[o1]=nn;
int ax=1ll*ns%mod*inv(nn%mod)%mod;
an[o1]=nn?(1ll*(ps2[rr]-ps2[ll-1]+mod)%mod+1ll*ax*ax%mod*nn%mod-2ll*(ps1[rr]-ps1[ll-1]+mod)%mod*ax%mod)%mod:0;
an[o1]+=an[o1]<0?mod:0;
while(tl)
{
int o=st[tl--];
sm[o]=sm[ch[o][0]]+sm[ch[o][1]],nm[o]=nm[ch[o][0]]+nm[ch[o][1]],an[o]=(an[ch[o][0]]+an[ch[o][1]])%mod;
rsm[o]=rsm[ch[o][1]],rnm[o]=rnm[ch[o][1]];
}
}
struct node
{
LL x;
int y;
node(){x=y=0;}
node(LL ns,int nn){x=ns,y=nn;}
node operator + (const node &bb) const {return node(x+bb.x,y+bb.y);}
};
node quer(int o,int l,int r,int ll,int rr)
{
if(ll>rr||!o) return node(0,0);
if(ll<=l&&r<=rr) return node(sm[o],nm[o]);
int mid=(l+r)>>1;
node an;
if(ll<=mid) an=an+quer(ch[o][0],l,mid,ll,rr);
if(rr>mid) an=an+quer(ch[o][1],mid+1,r,ll,rr);
return an;
}
node quer(int o,int l,int r,int lx)
{
if(!o) return node(0,0);
if(l==r) return node(sm[o],nm[o]);
int mid=(l+r)>>1;
if(lx<=mid) return quer(ch[o][0],l,mid,lx);
return quer(ch[o][1],mid+1,r,lx);
}
int getan(int o,int l,int r,int ll,int rr)
{
if(ll>rr||!o) return 0;
if(ll<=l&&r<=rr) return an[o];
int mid=(l+r)>>1,an=0;
if(ll<=mid) an+=getan(ch[o][0],l,mid,ll,rr);
if(rr>mid) an+=getan(ch[o][1],mid+1,r,ll,rr);
return an%mod;
}
int cmp(LL s1,LL n1,LL s2,LL n2)
{
s1*=n2,s2*=n1;
if(s1==s2) return 0;
return s1>s2?1:-1;
}
int nl;
node querl(int o,node aa)
{
node an;
int l=1,r=n;
while(l<r)
{
int mid=(l+r)>>1;
node ar=aa+an+node(sm[ch[o][1]],nm[ch[o][1]]),al=node(rsm[ch[o][0]],rnm[ch[o][0]])+ar;
if(cmp(al.x,al.y,ar.x,ar.y)<0) o=ch[o][1],l=mid+1;
else an=an+node(sm[ch[o][1]],nm[ch[o][1]]),o=ch[o][0],r=mid;
}
node ar=aa+an,al=node(sm[o],nm[o])+ar;
if(cmp(al.x,al.y,ar.x,ar.y)>0) an=an+node(sm[o],nm[o]);
nl=l;
return an;
}
int main()
{
n=rd(),m=rd();
for(int i=1;i<=n;++i)
{
a[i]=rd();
ps1[i]=(ps1[i-1]+a[i])%mod;
ps2[i]=(ps2[i-1]+1ll*a[i]%mod*a[i]%mod)%mod;
}
for(int i=1;i<=n;++i)
{
int las=tp;
sta[++tp][0]=a[i],sta[tp][1]=1;
while(tp>1&&cmp(sta[tp-1][0],sta[tp-1][1],sta[tp][0],sta[tp][1])>=0)
sta[tp-1][0]+=sta[tp][0],sta[tp-1][1]+=sta[tp][1],--tp;
rt1[i]=rt1[i-1];
for(int j=las;j>=tp;--j)
{
int la=rt1[i];
inst(rt1[i]=++tt,la,j,j,j,0,0);
}
int la=rt1[i];
inst(rt1[i]=++tt,la,tp,i-sta[tp][1]+1,i,sta[tp][0],sta[tp][1]);
len1[i]=tp;
}
tp=0;
for(int i=n;i;--i)
{
int las=tp;
sta[++tp][0]=a[i],sta[tp][1]=1;
while(tp>1&&cmp(sta[tp-1][0],sta[tp-1][1],sta[tp][0],sta[tp][1])<=0)
sta[tp-1][0]+=sta[tp][0],sta[tp-1][1]+=sta[tp][1],--tp;
rt2[i]=rt2[i+1];
for(int j=las;j>=tp;--j)
{
int la=rt2[i];
inst(rt2[i]=++tt,la,j,j,j,0,0);
}
int la=rt2[i];
inst(rt2[i]=++tt,la,tp,i,i+sta[tp][1]-1,sta[tp][0],sta[tp][1]);
len2[i]=tp;
}
printf("%d\n",an[rt1[n]]);
while(m--)
{
int x=rd(),y=rd();
int l=1,r=len2[x+1],z=0;
while(l<=r)
{
int mid=(l+r)>>1;
node a1=quer(rt2[x+1],1,n,mid,len2[x+1])+node(y,1),a2=mid>1?quer(rt2[x+1],1,n,mid-1):node(1e14,1);
if(cmp(a1.x,a1.y,a2.x,a2.y)<0) z=mid,l=mid+1;
else r=mid-1;
}
int z1=len1[x-1]+1,z2=0;
l=1,r=z+1;
while(l<=r)
{
int mid=(l+r)>>1;
node a1=quer(rt2[x+1],1,n,mid,len2[x+1])+node(y,1);
node a2=querl(rt1[x-1],a1),a3=mid>1?quer(rt2[x+1],1,n,mid-1):node(1e14,1);
if(cmp((a1+a2).x,(a1+a2).y,a3.x,a3.y)<0) z1=nl,z2=mid,l=mid+1;
else r=mid-1;
}
node a1=quer(rt1[x-1],1,n,z1,len1[x-1]),a2=quer(rt2[x+1],1,n,z2,len2[x+1]),aa=a1+a2+node(y,1);
int ll=x-a1.y,rr=x+a2.y,ax=1ll*aa.x%mod*inv(aa.y%mod)%mod;
int ans=(((1ll*ps2[rr]-ps2[ll-1]-1ll*a[x]*a[x]+1ll*y*y)%mod+mod)%mod+1ll*ax*ax%mod*(rr-ll+1)%mod-2ll*(1ll*ps1[rr]-ps1[ll-1]-a[x]+y+mod+mod)%mod*ax%mod)%mod;
ans+=ans<0?mod:0;
printf("%lld\n",(1ll*ans+getan(rt1[x-1],1,n,1,z1-1)+getan(rt2[x+1],1,n,1,z2-1))%mod);
}
return 0;
}
luogu P5294 [HNOI2019]序列的更多相关文章
- 【题解】Luogu P5294 [HNOI2019]序列
原题传送门 题意:给你一个长度为\(n\)的序列\(A\),每次询问修改一个元素(只对当前询问有效),然后让你找到一个不下降序列\(B\),使得这两个序列相应位置之差的平方和最小,并输出这个最小平方和 ...
- [luogu P3648] [APIO2014]序列分割
[luogu P3648] [APIO2014]序列分割 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序 ...
- [Luogu 2642] 双子序列最大和
Description 给定一个长度为n的整数序列,要求从中选出两个连续子序列,使得这两个连续子序列的序列和之和最大,最终只需输出最大和.一个连续子序列的和为该子序列中所有数之和.每个连续子序列的最小 ...
- luogu P5288 [HNOI2019]多边形
传送门 这是什么神仙操作... 首先要注意一些性质.首先每一个\((x,n)\)的边可以把当前多边形分成两半,这两半的操作是独立的.然后对于某一个没有\((x,n)\)的边的多边形,最优操作是唯一的. ...
- 【题解】Luogu P2572 [SCOI2010]序列操作
原题传送门:P2572 [SCOI2010]序列操作 这题好弱智啊 裸的珂朵莉树 前置芝士:珂朵莉树 窝博客里对珂朵莉树的介绍 没什么好说的自己看看吧 操作1:把区间内所有数推平成0,珂朵莉树基本操作 ...
- Luogu 3321 [SDOI2015]序列统计
BZOJ 3992 点开这道题之后才发现我对原根的理解大概只停留在$998244353$的原根是$3$…… 关于原根: 点我 首先写出$dp$方程,设$f_{i, j}$表示序列长度为$i$当前所有数 ...
- 【洛谷5294】[HNOI2019] 序列(主席树维护单调栈+二分)
点此看题面 大致题意: 给你一个长度为\(n\)的序列\(A\),每次询问修改一个元素(只对当前询问有效),然后让你找到一个不下降序列\(B\),使得这两个序列相应位置之差的平方和最小,并输出这个最小 ...
- 匈牙利算法 - Luogu 1963 变换序列
P1963 变换序列 题目描述 对于N个整数0,1,-,N-1,一个变换序列T可以将i变成Ti,其中:Ti∈{0,1,-,N-1}且 {Ti}={0,1,-,N-1}. x,y∈{0,1,-,N-1} ...
- 【Luogu P1631】序列合并
Luogu P1631 题意很好懂,不作分析 很容易想出一个解法是求出每一个和,排序后取前n个. 当然这种做法妥妥的会MLE+TLE 我们会发现实质上这种做法的缺点在于存入了大量不需要的数据. 那么该 ...
随机推荐
- .net 获取远程访问的ip
这两天一直做获取远程访问的ip和自己的ip相关的问题. 在解决获取ip相关问题的时候,主要使用了上下文对象,httpcontext对象.原理很简单,内部有两大对象,request和response.里 ...
- SpringBoot2.0之四 简单整合MyBatis
从最开始的SSH(Struts+Spring+Hibernate),到后来的SMM(SpringMVC+Spring+MyBatis),到目前的S(SpringBoot),随着框架的不断更新换代,也为 ...
- 《JAVA程序设计》_第三周学习总结
20175217吴一凡 一.IDEA学生免费版申请后续 收到这个邮件,就说明你申请成功了,点这里进去就行了 点击接受 在下一个界面登录你之前注册的账号绑定许可证就行了,重新登录你的账号就有了一年的许可 ...
- 第十届蓝桥杯省赛JavaB组个人题解
前言 以下的第十届蓝桥杯Java B组省赛的题目题解只是我个人的题解,提供一些解题思路,仅作参考,如有错误,望大家指出,不甚感激,我会及时更改. 试题 A: 组队 ----- 答案:490 [问题描述 ...
- DeeplabV3+ 命令行不显示miou的解决
首先看到训练时会在命令行里输出 loss 和 total loss,那是怎么做到的呢,通过分析 train.py 源码,看到如下代码 total_loss = tf.cond( should_log, ...
- SkylineGlobe TerraExplorer for Web 7.1.0版本 接口示例
在SkylineGlobe TerraExplorer for Web 7.1.0版本(俗称H5免插件版本)中,如何使用SGWorld接口的三维视域分析方法呢? 请参考下面的示例: 通过下面的代码大家 ...
- Luogu4755 Beautiful Pair 最值分治、主席树
传送门 整天做一些模板题感觉药丸 设\(val_i\)表示第\(i\)个位置的值 看到区间最大值考虑最值分治.对于当前的区间\([l,r]\),找到区间最大值\(mid\),递归\([l,mid-1] ...
- enex 转 md 格式的几种方式(免费版/氪金版)
因为最近有读者投稿,用的是印象笔记,文件格式为 .enex ,一般发文章都用 markdown 格式,这叫我好生苦恼,于是乎,Google 搜了一下,找到了如下解决办法. 氪金版: 我只找到了一款比较 ...
- 使用IDEA2017在Windows下编程并测试Hadoop2.7+Spark2.2+Azkaban
1. 下载好IDEA HADOOP SPARK 首先,配置IDEA, 在插件管理中使用IDEA在线库安装scala插件, 在在线库直接搜索即可; 其次,配置Maven选项, 将Maven添加到IDEA ...
- vue 使用微信JSSDK,在IOS端会授权出错
原因: vue-router切换的时候操作的都是浏览器的历史记录,iOS会把第一次刚进入时的URL作为真实URL,安卓会把当前URL作为真实URL. 所以导致后端在配置好的授权参数获得的config参 ...