题目大意:给你一个长度为$n$的序列$a$,请你求:

$\sum\limits_{l=1}^{n}\sum\limits_{r=l}^{n}\dfrac{mex(a_l,a_{l+1},...,a_r)}{r-l+1}$

对998244353取模

数据范围:$n≤5\times 10^5$

我们考虑把原先的式子转化一下

令$s[i]=\sum\limits_{j=1}^{i} \frac{1}{i}$。

令$f[i][l]$表示最小的$x$,满足$mex(a_l,a_{l+1},...,a_x)≥i$。若找不到这样的$x$,$f[i][l]=n+1$

不难发现,原先答案的式子我们可以转化:

$\sum\limits_{i=1}^{lim}\sum\limits_{l=1}^{n}s[n-l+1]-s[f[i][l]-l]$

其中lim表示最大的数x,满足0到x-1中的数都出现过

然后我们发现,当i不变时,$f[i]$的值是递增的,且有大量的值是相同的,且以区间的形式出现。

我们可以基于这个性质,通过线段树打标记,快速地将$f[i]$的值更新至$f[i+1]$。

线段树统计的同时维护答案的式子,每次累加即可。

 #include<bits/stdc++.h>
#define M (1<<19)
#define L long long
#define mid ((a[x].l+a[x].r)>>1)
#define MOD 998244353
using namespace std; L pow_mod(L x,L k){L ans=;for(;k;k>>=,x=x*x%MOD) if(k&) ans=ans*x%MOD; return ans;}
L inv[M]={},s[M]={},n;
L S(int l,int r){return (s[r]-s[max(l-,)]+MOD)%MOD;} struct seg{int l,r,tag,minn,maxn;L sum;}a[M*]; void pushup(int x){
a[x].minn=min(a[x<<].minn,a[x<<|].minn);
a[x].maxn=max(a[x<<].maxn,a[x<<|].maxn);
a[x].sum=(a[x<<].sum+a[x<<|].sum);
}
void upd(int x,int k){
a[x].tag=a[x].minn=a[x].maxn=k;
a[x].sum=S(k-a[x].r,k-a[x].l);
}
void pushdown(int x){
if(a[x].tag) upd(x<<,a[x].tag),upd(x<<|,a[x].tag);
a[x].tag=;
} int build(int x,int l,int r){
a[x].l=l; a[x].r=r; if(l==r) return a[x].minn=a[x].maxn=l;
build(x<<,l,mid); build(x<<|,mid+,r); pushup(x);
} void updata(int x,int l,int r,int k){
if(a[x].minn>=k) return;
if(a[x].l==a[x].r){
a[x].minn=a[x].maxn=max(a[x].maxn,k);
a[x].sum=S(k-a[x].l,k-a[x].l);
return;
}
if(l<=a[x].l&&a[x].r<=r){
if(a[x].maxn<k){
upd(x,k);
return;
}
}
pushdown(x);
if(l<=mid) updata(x<<,l,r,k);
if(mid<r) updata(x<<|,l,r,k);
pushup(x);
} struct node{
int x,id; node(){x=id=;}
friend bool operator <(node a,node b){return a.x==b.x?a.id<b.id:a.x<b.x;}
}p[M]; int main(){
for(int i=;i<M;i++) inv[i]=pow_mod(i,MOD-);
for(int i=;i<M;i++) s[i]=(s[i-]+inv[i])%MOD;
for(int i=;i<M;i++) s[i]=(s[i-]+s[i])%MOD; scanf("%d",&n); build(,,n);
for(int i=;i<=n;i++) scanf("%d",&p[i].x),p[i].id=i;
sort(p+,p+n+); p[].x=-; p[n+].x=; L ans=,hh=; for(int i=,j=;i<=n;hh++){
if(p[i].x!=p[i-].x+) break;
while(p[i].x==p[j].x) j++; for(int last=;i<=j;i++){
if(i==j){
if(last<n) updata(,last+,n,n+);
break;
}
updata(,last+,p[i].id,p[i].id);
last=p[i].id;
} ans=(ans+a[].sum)%MOD;
} cout<<(s[n]*hh-ans+MOD)%MOD<<endl;
}

【xsy2274】 平均值 线段树的更多相关文章

  1. 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

    3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] ...

  2. ural1855 线段树区间更新+推公式维护一元二次式

    和威威猫系列故事差不多,都是根据条件推出公式 /* 操作c a b d:a到b道路上的所有边权值加d 操作e a b:问a到b中包含的道路的平均权值 区间平均值=所有可能路径权值/所有路径数, 而路径 ...

  3. 51Nod 1199 Money out of Thin Air (树链剖分+线段树)

    1199 Money out of Thin Air  题目来源: Ural 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 一棵有N个节点的树,每 ...

  4. 线段树(I tree)

    Codeforces Round #254 (Div. 2)E题这题说的是给了一个一段连续的区间每个区间有一种颜色然后一个彩笔从L画到R每个区间的颜色都发生了 改变然后 在L和R这部分区间里所用的颜色 ...

  5. 【洛谷】【线段树】P1471 方差

    [题目背景:] 滚粗了的HansBug在收拾旧数学书,然而他发现了什么奇妙的东西. [题目描述:] 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差 ...

  6. bzoj 3779 重组病毒 好题 LCT+dfn序+线段树分类讨论

    题目大意 1.将x到当前根路径上的所有点染成一种新的颜色: 2.将x到当前根路径上的所有点染成一种新的颜色,并且把这个点设为新的根: 3.查询以x为根的子树中所有点权值的平均值. 分析 原题codec ...

  7. Bzoj 2752 高速公路 (期望,线段树)

    Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时 ...

  8. ZOJ 2706 Thermal Death of the Universe (线段树)

    题目链接:ZOJ 2706 Thermal Death of the Universe (线段树) 题意:n个数.m个操作. 每一个操作(a,b)表示(a,b)全部值更新为这个区间的平均数:1.当前的 ...

  9. Atcoder E - Meaningful Mean(线段树+思维)

    题目链接:http://arc075.contest.atcoder.jp/tasks/arc075_c 题意:问数组a有多少子区间平均值为k 题解:一开始考虑过dp,但是显然不可行,其实将每一个数都 ...

随机推荐

  1. vue+mui轮播图

    mui的轮播图,如果图片是请求来的,直接在html中循环是不会动的. 需要请求完图片之后,在setTimeout方法里,使用slider()方法,这样才会动 而且mui的轮播图,有点坑的,需要重复最后 ...

  2. C++IO cin

    cin cin.get() 每次只读缓冲区一个字符,不能接收空格 cin.getline() 读缓冲区一行,能够接收空格 cin.ignore(2) 忽略缓冲器2个字节 int i = cin.pee ...

  3. Andrew机器学习第一课

    批梯度下降算法:      训练样本为一个时:更新Θi 让代价函数最小,利用沿梯度下降方向函数会变得越来越小.这个函数是代价函数J关于(Θi )的.这里并没有在讨论x,y. 关于为什么式子(图是复制的 ...

  4. 安卓开机logo和开机动画的几种实现方法

    安卓4.2可用方法2-4,第一种方法未验证. 从理论上来说,android 有4个开机启动画面. 第一个应该是U-BOOT的启动画面,有些设备为了满足按动电源即有显示,在UBOOT里加了开机画面,实现 ...

  5. python处理中文

    python 清洗中文文件 需要用到的两个链接: 1,unicode编码转换器 http://www.bangnishouji.com/tools/chtounicode.html 2,Python匹 ...

  6. 泡泡机器人SLAM 2019

    LDSO:具有回环检测的直接稀疏里程计:LDSO:Direct Sparse Odometry with Loop Closure Abstract—In this paper we present ...

  7. sys/time.h 和 time.h

    今天在燕麦工作第二天.看荣哥给我的程序,发现程序里面用的延时跟我以前使用的不同.导入两个头文件,然后用函数来获得时间.关于这个函数特别查来一下. time.h  是ISO C99 标准日期头文件. s ...

  8. Hdu4185 Oil Skimming

    Oil Skimming Problem Description Thanks to a certain "green" resources company, there is a ...

  9. TF-IDF模型的概率解释

    信息检索概述 信息检索是当前应用十分广泛的一种技术,论文检索.搜索引擎都属于信息检索的范畴.通常,人们把信息检索问题抽象为:在文档集合D上,对于由关键词w[1] … w[k]组成的查询串q,返回一个按 ...

  10. cxGrid 的 Sorting和Filtering的总开关