【JZOJ4939】平均值 题解
题目大意
给定一个长度为 nnn 的序列 a1,⋯,ana_1,\cdots,a_na1,⋯,an,求所有区间的 mexmexmex 平均值之和,即
∑l=1n∑r=lnmex(al,al+1,⋯,ar)r−l+1(mod998244353)\sum_{l=1}^n\sum_{r=l}^n \frac{mex(a_l,a_{l+1},\cdots,a_r)}{r-l+1} \pmod{998244353} l=1∑nr=l∑nr−l+1mex(al,al+1,⋯,ar)(mod998244353)
1≤n≤5×105,0≤ai≤5×1051 \leq n \leq 5 \times 10^5,~~0 \leq a_i \leq 5 \times 10^51≤n≤5×105, 0≤ai≤5×105
\\
\\
\\
题解
这题大概是有两种解法,官方题解是转化成 ∑i=0max{a}∑l≤r[mex(al,⋯,ar)≥i]r−l+1\sum_{i=0}^{\max\{a\}}\sum_{l \leq r} \frac{[mex(a_l,\cdots,a_r) \geq i]}{r-l+1}∑i=0max{a}∑l≤rr−l+1[mex(al,⋯,ar)≥i] 来做,但它比较简略我没搞懂。于是又找到了HOWARLI的做法,我这个就是参考他的。被吊打啦
有一种传统建模是,左端点从右往左移动,用线段树维护右端点的答案。但是在这题,左端点往左移相当于给若干个序列插入一个元素, mexmexmex 怎么变就很难搞了。
但是变通一下,左端点从左往右移,就很好搞了。因为这对于 mexmexmex 来说相当于是区间取 min\minmin 的操作。
当左端点从 i−1i-1i−1 移到 iii,就相当于删去 ai−1a_{i-1}ai−1,假设 i−1i-1i−1 后面的第一个跟 ai−1a_{i-1}ai−1 相同的元素是 anexti−1a_{next_{i-1}}anexti−1,那么删去 ai−1a_{i-1}ai−1 影响到的右端点范围就是 [i,nexti−1)[i,next_{i-1})[i,nexti−1)。在这个范围里所有 mexmexmex 值大于 ai−1a_{i-1}ai−1 的都会变成 ai−1a_{i-1}ai−1。
由于 mexmexmex 是分段递增的,我们在这个范围内找到所有 mexmexmex 值大于 ai−1a_{i-1}ai−1 的段,结算它们的贡献,并更新它们。
假设一个段 [l,r][l,r][l,r],mexmexmex 值为 mmm。对于里面的一个元素 x(x∈[l,r])x~(x \in [l,r])x (x∈[l,r]),它最早在左端点为 ttt 时把 mexmexmex 值更新为 mmm,那么它要结算的贡献就是 m(1x−t+1+⋯+1x−(i−1)+1)m(\frac{1}{x-t+1}+\cdots+\frac{1}{x-(i-1)+1})m(x−t+11+⋯+x−(i−1)+11),即 m(sx−t+1−sx−(i−1))m(s_{x-t+1}-s_{x-(i-1)})m(sx−t+1−sx−(i−1))(记 sn=∑i=1n1is_n=\sum_{i=1}^n \frac 1isn=∑i=1ni1)。
于是用线段树维护一下 mexmexmex 的分段、区间 ∑sx−t+1\sum s_{x-t+1}∑sx−t+1 即可。
每次左端点的移动,最多新增 2 个段,删除若干个段,因此段的总量也是 O(n)O(n)O(n) 的。时间复杂度 O(nlogn)O(n \log n)O(nlogn)。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;typedef long long LL;const int maxn=5e5+5;
const LL mo=998244353;struct TR{int minmex,maxmex;LL st;
};int n,a[maxn];LL Pow(LL x,LL y)
{LL re=1;for(; y; y>>=1, x=x*x%mo) if (y&1) re=re*x%mo;return re;
}int ap[maxn],nxt[maxn],init_mex[maxn];
LL s[maxn],ss[maxn];
void Pre()
{fd(i,n,1){nxt[i]=(!ap[a[i]]) ?n+1 :ap[a[i]];ap[a[i]]=i;}memset(ap,0,sizeof(ap));int mex=0;fo(i,1,n){ap[a[i]]=1;while (ap[mex]) mex++;init_mex[i]=mex;}fo(i,1,n) s[i]=(s[i-1]+Pow(i,mo-2))%mo, ss[i]=(ss[i-1]+s[i])%mo;
}TR tr[4*maxn];
pair<int,int> bz[4*maxn];
TR merge(const TR &a,const TR &b)
{return (TR){min(a.minmex,b.minmex),max(a.maxmex,b.maxmex),(a.st+b.st)%mo};
}
void update(int k,int t,int l,int mid,int r)
{if (!bz[k].first) return;tr[t]=(TR){bz[k].second,bz[k].second,(ss[mid-bz[k].first+1]-ss[l-bz[k].first]+mo)%mo};tr[t+1]=(TR){bz[k].second,bz[k].second,(ss[r-bz[k].first+1]-ss[mid+1-bz[k].first]+mo)%mo};bz[t]=bz[t+1]=bz[k];bz[k]=make_pair(0,0);
}
void tr_js(int k,int l,int r)
{if (l==r){tr[k]=(TR){init_mex[r],init_mex[r],s[r]};return;}int t=k<<1, mid=(l+r)>>1;tr_js(t,l,mid), tr_js(t+1,mid+1,r);tr[k]=merge(tr[t],tr[t+1]);
}
pair<int,int> cx_bs(int k,int l,int r,int x,int z)
{if (l==r) return (tr[k].maxmex>z) ?make_pair(l,tr[k].maxmex) :make_pair(-1,-1) ;int t=k<<1, mid=(l+r)>>1;update(k,t,l,mid,r);return (x<=mid && tr[t].maxmex>z) ?cx_bs(t,l,mid,x,z) :cx_bs(t+1,mid+1,r,x,z);
}
int cx_r(int k,int l,int r,int x,int z)
{if (l==r) return l;int t=k<<1, mid=(l+r)>>1;update(k,t,l,mid,r);return (x<=mid && tr[t+1].minmex>z) ?cx_r(t,l,mid,x,z) :cx_r(t+1,mid+1,r,x,z);
}
LL cx_st(int k,int l,int r,int x,int y)
{if (x<=l && r<=y) return tr[k].st;int t=k<<1, mid=(l+r)>>1;update(k,t,l,mid,r);LL re=0;if (x<=mid) re=cx_st(t,l,mid,x,y);if (mid<y) (re+=cx_st(t+1,mid+1,r,x,y))%=mo;return re;
}
void tr_xg(int k,int l,int r,int x,int y,pair<int,int> z)
{if (x<=l && r<=y){tr[k]=(TR){z.second,z.second,(ss[r-z.first+1]-ss[l-z.first]+mo)%mo};bz[k]=z;return;}int t=k<<1, mid=(l+r)>>1;update(k,t,l,mid,r);if (x<=mid) tr_xg(t,l,mid,x,y,z);if (mid<y) tr_xg(t+1,mid+1,r,x,y,z);tr[k]=merge(tr[t],tr[t+1]);
}int main()
{freopen("average.in","r",stdin);freopen("average.out","w",stdout);scanf("%d",&n);fo(i,1,n) scanf("%d",&a[i]);Pre();tr_js(1,1,n);LL ans=0;fo(i,1,n){if (i>1){for(int l=i, r; l<nxt[i-1]; l=r+1){pair<int,int> t=cx_bs(1,1,n,l,a[i-1]);l=t.first;if (l==-1 || l>=nxt[i-1]) break;r=min(cx_r(1,1,n,l,t.second),nxt[i-1]-1);(ans+=(cx_st(1,1,n,l,r)-ss[r-(i-1)]+mo+ss[l-(i-1)-1])%mo*t.second)%=mo;tr_xg(1,1,n,l,r,make_pair(i,a[i-1]));}}(ans+=cx_st(1,1,n,i,i)*(a[i]==0))%=mo;}printf("%lld\n",ans);
}
【JZOJ4939】平均值 题解相关推荐
- 【HDU-2376】Average distance
[HDU-2376]Average distance 题意: 给你一个树,求树上任意两个点之间的距离的平均值 题解: 就是求出任意两点之间的距离和然后除以边数 "任意两点之间的距离" ...
- LuoguP4233 射命丸文的笔记
题目描述 求所有\(n\)个点带标号强连通竞赛图中哈密顿回路数量的平均值. 题解 因为要求平均数,所以我们可以把分母和分子单开来算. \(n\)个点的所有竞赛图的所有哈密顿回路个数是可以求出来的,就是 ...
- 2020 CCPC Wannafly Winter Camp Day2 Div.12——A 托米的字符串【构造、数学】
题目传送门 题目描述 托米有一个字符串,他经常拿出来玩.这天在英语课上,他学习了元音字母 a , e , i , o , u {a,e,i,o,u} a,e,i,o,u 以及半元音 y {y} y . ...
- codeforces 1003A. Polycarp's Pockets,C. Intense Heat(暴力)
A. Polycarp's Pockets 题目链接:codeforces 1003A 题意: 给n个数,要求相同的数不能放在一个口袋,问最少需要多少个口袋 题解: 求出最多的相同数 ...
- Python编程PTA题解——大于身高的平均值
Python编程PTA题解大全--索引 Description:中小学生每个学期都要体检,要量身高,因为身高可以反映孩子的生长状况.现在,一个班的身高已经量好了,请输出其中超过平均身高的那些身高.程序 ...
- zzuli 20级新生周赛(1)题解
前言:涉及了字符串的题运用了string类,比char要方便很多,建议学习. 文章目录 A.藏头诗 B.画剑 C.商品总数 D. 小"光棍节" E.神秘的123 F.黄河大鲤鱼 G ...
- BZOJ 2133 切割(树形DP,树上背包)大概是本题全网第一篇题解 >_<【BZOJ 修复工程】
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 BZOJ 2133 切割这道题全网搜不到任何一篇题解 >_< 看评测记录也没有几个人AC- ...
- 2018 ACM-ICPC Asia Shenyang Regional Contest 题解(9 / 13)【每日亿题2021/2/24】
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A.(2018 ACM-ICPC Shenyang J)How Much Memory Your ...
- 我花了三个小时写了一道题的六千字题解....(POJ 2888 Magic Bracelet)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 前置知识:小学生都能看懂的群论从入门到升天教程 <群论全家桶> 一道简单的题目 Probl ...
- POJ 2976 Dropping tests【二分 最大化平均值】
题意:定义最大平均分为 (a1+a2+a3+---+an)/(b1+b2+---+bn),求任意去除k场考试的最大平均成绩 和挑战程序设计上面的最大化平均值的例子一样 判断是否存在x满足条件 (a1+ ...
最新文章
- 在Linux下编写Daemon
- 2020-09-18
- MAC 重置MySQL root 密码
- java 模拟ajax上传图片
- ssm路径访问不到_ssm整合!!!
- 魔兽嘉年华,云信四大码魔与你不见不散
- .net 把一个对象赋值给一个参数_Java GC回收算法-判定一个对象是否可以回收
- 【从入门到放弃-Java】并发编程-线程安全
- 敏捷外包工程系列之三:固定合同(敏捷外包工程,敏捷开发,产品负责人,客户价值)...
- win98 支持html5,win98 ghost ghost在WIN98怎么使用
- CC2500 使用总结
- java poi dataformat_poi的data format可真不怎么样
- php源码添加多国语言包,为win7系统添加多国语言包的方法
- html canvas 绘制转盘,Canvas绘制转盘
- window.open用法详解
- 计算机毕业设计Python+uniapp学生考勤系统小程序(小程序+源码+LW)
- 长理2019选拔赛1.0
- git Incorrect username or password (access token)问题解决
- 水清冷冷:PSCC2019/PSCC2020安装教程和学习技巧(附工具)
- 在iPhone上如何备份WhatsApp数据
热门文章
- 深大计算机与软件学院学生,深圳大学
- Docker启动报错“Job for docker.service failed because a configured resource limit was exceeded.
- pe制作linux硬盘的镜像文件_用WindowsPE制作的启动U盘或移动硬盘安装cent os 6.2
- lotus notes 闪退_win7系统Lotus Notes邮箱闪退的解决方法
- springboot将模板生成pdf文件
- P3966 [TJOI2013]单词(AC自动机,Trie图)
- 织梦网站模板的建站优势
- python安全工具开发应用_2019年顶级应用安全工具
- SSM框架-Spring(一)
- 整型常量是整数类型的数据