【xsy2274】 平均值 线段树
题目大意:给你一个长度为$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】 平均值 线段树的更多相关文章
- 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序
3779: 重组病毒 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 224 Solved: 95[Submit][Status][Discuss] ...
- ural1855 线段树区间更新+推公式维护一元二次式
和威威猫系列故事差不多,都是根据条件推出公式 /* 操作c a b d:a到b道路上的所有边权值加d 操作e a b:问a到b中包含的道路的平均权值 区间平均值=所有可能路径权值/所有路径数, 而路径 ...
- 51Nod 1199 Money out of Thin Air (树链剖分+线段树)
1199 Money out of Thin Air 题目来源: Ural 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 一棵有N个节点的树,每 ...
- 线段树(I tree)
Codeforces Round #254 (Div. 2)E题这题说的是给了一个一段连续的区间每个区间有一种颜色然后一个彩笔从L画到R每个区间的颜色都发生了 改变然后 在L和R这部分区间里所用的颜色 ...
- 【洛谷】【线段树】P1471 方差
[题目背景:] 滚粗了的HansBug在收拾旧数学书,然而他发现了什么奇妙的东西. [题目描述:] 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差 ...
- bzoj 3779 重组病毒 好题 LCT+dfn序+线段树分类讨论
题目大意 1.将x到当前根路径上的所有点染成一种新的颜色: 2.将x到当前根路径上的所有点染成一种新的颜色,并且把这个点设为新的根: 3.查询以x为根的子树中所有点权值的平均值. 分析 原题codec ...
- Bzoj 2752 高速公路 (期望,线段树)
Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时 ...
- ZOJ 2706 Thermal Death of the Universe (线段树)
题目链接:ZOJ 2706 Thermal Death of the Universe (线段树) 题意:n个数.m个操作. 每一个操作(a,b)表示(a,b)全部值更新为这个区间的平均数:1.当前的 ...
- Atcoder E - Meaningful Mean(线段树+思维)
题目链接:http://arc075.contest.atcoder.jp/tasks/arc075_c 题意:问数组a有多少子区间平均值为k 题解:一开始考虑过dp,但是显然不可行,其实将每一个数都 ...
随机推荐
- 2018.12.15 bzoj3998: [TJOI2015]弦论(后缀自动机)
传送门 后缀自动机基础题. 求第kkk小的子串(有可能要求本质不同) 直接建出samsamsam,然后给每个状态赋值之后在上面贪心选最小的(过程可以类比主席树/平衡树的查询操作)即可. 代码: #in ...
- DevExpress 只允许修改指定列
gridView1.OptionsBehavior.Editable = true; gridView1.OptionsBehavior.ReadOnly = false; foreach (Grid ...
- excel 错误提示以及其他基础知识
http://wenda.tianya.cn/question/05a3d11b0e4f3c34 For i = 1 To ActiveSheet.ChartObjects.Count M ...
- Apache hadoop安装配置
1.网络中继更改问题 命令: vi /etc/sysconfig/network-scripts/ifcfg-eth0 需要修改的代码 DEVICE=eth0 HWADDR=00:0C:29:11 ...
- PHP continue break 区别 用法
<?php //continue 跳过当前循环,进行下一个 //break 终止当前循环 $db=new PDO("mysql:host=localhost;dbname=root&q ...
- 行转列group_concat()函数妙用
测试环境准备: mysql> create table test01(name varchar(20),address varchar(20)); Query OK, 0 rows affect ...
- RuntimeException
Throwable Error ... Exception !RuntimeException RuntimeException 两类:checked exceptions 和 unchecked e ...
- C++类、继承、多态、虚函数
一个比较好的虚函数例子 /****************************/ /* 作者:骆天 */ /* 时间:2018/1/26 */ /* 代码:多态的理解 */ /********** ...
- 20170831工作日记--自定义View学习
学习了LayoutInflater的原理分析.视图的绘制流程.视图的状态及重绘等知识,按类型来划分的话,自定义View的实现方式大概可以分为三种,自绘控件.组合控件.以及继承控件.那么下面我们就来依次 ...
- (简单广搜) Ice Cave -- codeforces -- 540C
http://codeforces.com/problemset/problem/540/C You play a computer game. Your character stands on so ...