洛谷 P2221 [HAOI2012]高速公路
链接:
题意:
有 \(n(1\leq n\leq 10^5)\) 个点,从第 \(i(1\leq i< n)\) 个点向第 \(i+1\) 个点连有边。最初所有边长 \(v_i\) 为 \(0\)。
有 \(m(1\leq m\leq 10^5)\) 次操作:
- 操作 \(1\):
'C' l r v表示将 \(l\) 和 \(r\) 之间的所有边长度加上 \(v\)。 - 操作 \(2\):
'Q' l r在第 \(l\) 个到第 \(r\) 个点里等概率随机取出两个不同的点 \(a\) 和 \(b\),询问 \(a,b\) 的期望距离。
保证:\(1\leq l\leq r\leq n,-10^4\leq v\leq 10^4\),任意时刻满足 \(0\leq v_i\leq 10^4\)。
分析:
分析询问操作,显然是问距离的平均数,也就是\(\dfrac{\sum\limits_{i=l}^{r-1}\sum\limits_{j=i+1}^rdis[i][j]}{(r-l+1)\times(r-l)/2}\)。
分母可以直接算,分子比较难算。
首先化边为点,查询 \([l,r]\) 之间的边也就是 \([l,r-1]\) 的边。
考虑每条边被计算的次数,枚举左右两边的端点,则 \(ans=\sum\limits_{i=l}^{r-1}v[i]\times(i-l+1)\times(r-i+1)\)。
把式子拆开后得到:
\(ans=\sum\limits_{i=l}^{r-1}v[i]*i^2+(l+r)\sum\limits_{i=l}^{r-1}v[i]*i+(-l*r+r-l+1)*\sum\limits_{i=l}^{r-1}v[i]\)
\(\sum\) 前面的东西可以提出来,所以我们只需要每次查询 \(\sum\limits_{i=l}^{r-1}v[i]*i^2,\sum\limits_{i=l}^{r-1}v[i]*i,\sum\limits_{i=l}^{r-1}v[i]\)
线段树维护这三个值,分别记为 \(sum1,sum2,sum3\)
pushup 时直接相加:
inline void pushup(int p){
sum1(p)=sum1(p<<1)+sum1(p<<1|1);
sum2(p)=sum2(p<<1)+sum2(p<<1|1);
sum3(p)=sum3(p<<1)+sum3(p<<1|1);
}
修改时,\(sum1\) 加上 \(d*\sum\limits_{i=l}^ri^2\),\(sum2\) 加上 \(d*\sum\limits_{i=l}^ri\),\(sum3\) 加上 \(d*\sum\limits_{i=l}^r1\)。这些东西都可以 \(O(1)\) 搞出来。
所以分子就维护好了。
由于对边的操作需要我们让 \(r-1\),但分母中的 \(r\) 不能减,所以在 \(r-1\) 后,分母要变成 \((r-l+2)\times(r-l+1)/2\)。
于是这道题就做完了。时间复杂度 \(O(n\log n)\)。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
inline int read(){
int p=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}
return p*f;
}
const int N=1e5+5;
int n,m;
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
#define sum1(x) t[x].sum1
#define sum2(x) t[x].sum2
#define sum3(x) t[x].sum3
#define tag(x) t[x].tag
inline int sumi1(int l,int r){return (l+r)*(r-l+1)/2;}
inline int sumi2(int l,int r){return r*(r+1)/2*(2*r+1)/3-(l-1)*l/2*(2*l-1)/3;}
struct node{
int sum1,sum2,sum3,tag;
}t[N<<2];
inline void pushup(int p){
sum1(p)=sum1(p<<1)+sum1(p<<1|1);
sum2(p)=sum2(p<<1)+sum2(p<<1|1);
sum3(p)=sum3(p<<1)+sum3(p<<1|1);
}
inline void f(int l,int r,int p,int d){
tag(p)+=d;
sum1(p)+=sumi2(l,r)*d;
sum2(p)+=sumi1(l,r)*d;
sum3(p)+=(r-l+1)*d;
}
inline void pushdown(int l,int r,int p){
if(tag(p)){
int mid=(l+r)>>1;
f(l,mid,p<<1,tag(p));
f(mid+1,r,p<<1|1,tag(p));
tag(p)=0;
}
}
inline void change(int l,int r,int p,int cl,int cr,int d){
if(l>=cl&&r<=cr){f(l,r,p,d);return ;}
pushdown(l,r,p);
int mid=(l+r)>>1;
if(cl<=mid)change(l,mid,p<<1,cl,cr,d);
if(cr>mid)change(mid+1,r,p<<1|1,cl,cr,d);
pushup(p);
}
struct ret{
int sum1,sum2,sum3;
};
ret operator+(const ret &x,const ret &y){
ret z;
z.sum1=x.sum1+y.sum1;
z.sum2=x.sum2+y.sum2;
z.sum3=x.sum3+y.sum3;
return z;
}
inline ret query(int l,int r,int p,int ql,int qr){
if(l>=ql&&r<=qr){return {sum1(p),sum2(p),sum3(p)};}
pushdown(l,r,p);
int mid=(l+r)>>1;
ret t={0,0,0};
if(ql<=mid)t=t+query(l,mid,p<<1,ql,qr);
if(qr>mid)t=t+query(mid+1,r,p<<1|1,ql,qr);
return t;
}
signed main(){
n=in,m=in;
for(int i=1;i<=m;i++){
char c[5];
cin>>c;
if(c[0]=='C'){
int l=in,r=in-1,d=in;
change(1,n,1,l,r,d);
}
else{
int l=in,r=in-1;
ret ans=query(1,n,1,l,r);
int ans1=-ans.sum1+(l+r)*ans.sum2+(r-l+1-l*r)*ans.sum3;
int ans2=(r-l+2)*(r-l+1)/2;
int t=gcd(ans1,ans2);
ans1/=t,ans2/=t;
cout<<ans1<<"/"<<ans2<<'\n';
}
}
return 0;
}
洛谷 P2221 [HAOI2012]高速公路的更多相关文章
- 洛谷P2221 [HAOI2012]高速公路
线段树 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> ...
- 洛谷P2221 [HAOI2012]高速公路(线段树+概率期望)
传送门 首先,答案等于$$ans=\sum_{i=l}^r\sum_{j=i}^r\frac{sum(i,j)}{C_{r-l+1}^2}$$ 也就是说所有情况的和除以总的情况数 因为这是一条链,我们 ...
- P2221 [HAOI2012]高速公路(线段树)
P2221 [HAOI2012]高速公路 显然答案为 $\dfrac{\sum_{i=l}^r\sum_{j=l}^{r}dis[i][j]}{C_{r-l+1}^2}$ 下面倒是挺好算,组合数瞎搞 ...
- 洛谷 P2220 [HAOI2012]容易题 数论
洛谷 P2220 [HAOI2012]容易题 题目描述 为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下: 有一个数列A已知对于所有的A[i]都是1~n的自然数 ...
- 洛谷P2221 高速公路【线段树】
题目:https://www.luogu.org/problemnew/show/P2221 题意:有n个节点排成一条链,相邻节点之间有一条路. C u v val表示从u到v的路径上的每条边权值都加 ...
- 洛谷 P2505 [HAOI2012]道路 解题报告
P2505 [HAOI2012]道路 题目描述 C国有n座城市,城市之间通过m条单向道路连接.一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它 ...
- 洛谷 P1877 [HAOI2012]音量调节
P1877 [HAOI2012]音量调节 题目描述 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都需要改变一次音量.在演出开始之前,他已经做好一个列表,里面 ...
- 洛谷P1877 [HAOI2012]音量调节 [2017年4月计划 动态规划05]
P1877 [HAOI2012]音量调节 题目描述 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都需要改变一次音量.在演出开始之前,他已经做好一个列表,里面 ...
- 【题解】Luogu P2221 [HAOI2012]高速公路
原题传送门 这道题还算简单 我们要求的期望值: \[\frac{\sum_{i=l}^r\sum_{j=l}^rdis[i][j]}{C_{r-l+1}^{2}}\] 当然是上下两部分分别求,下面肥肠 ...
随机推荐
- 2.1Java基础
2.1.9面向对象的三大特性(携程): 封装:把一个对象的属性隐藏在对象内部,外部对象不能直接访问这个对象的内部信息.但是可以提供一些可以被外界访问的方法来操作属性.就比如我们常常创建一个类,把他的属 ...
- python+echarts+flask实现对全国疫情数据的爬取并可视化展示
用Python进行数据爬取并存储到数据库,3.15学习总结(Python爬取网站数据并存入数据库) - 天岁 - 博客园 (cnblogs.com) 通过echarts+flask实现数据的可视化展示 ...
- Python爬无止境,获得王者荣耀全部高清皮肤
作为一名热爱王者两年的程序员,早就想爬取所有英雄皮肤的高清照片,在设个幻灯片放映,真香,这次只用16行代码就能实现,对于新手拿这个作为实战练手项目既简单又容易上手,快来尝试下. 百度"王者荣 ...
- Sentry 监控 - Search 搜索查询实战
系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...
- Linux系列(26) - 强制杀死进程
查进程 ps -ef ps -aux #上述两个均可 例子:ps -ef | grep "vim canshu2" 强杀进程 kill -s 9 进程id #命令格式 例子:ki ...
- 对帧率、I/P率、I帧间隔的理解
码率就是数据传输时单位时间传送的数据位数,一般我们用的单位是kbps即千位每秒.通俗一点的理解就是取样率,单位时间内取样率越大,精度就越高,处理出来的文件就越接近原始文件,但是文件体积与取样率是成正比 ...
- P2490-[SDOI2011]黑白棋【博弈论,dp】
正题 题目链接:https://www.luogu.com.cn/problem/P2490 题目大意 一个长度为\(n\)的棋盘上放下\(k\)个棋子. 第一个要是白色,下一个要是黑色,在下一个是白 ...
- 测试用例 setup 和 和 teardown
前言 学过unittest的都知道里面用前置和后置setup呾teardown非常好用,在每次用例开始前呾结束后都去执行一次.当然迓有更高级一点的 setupClass 呾 teardownClass ...
- kettle 多表全删全插同步数据 两种方案
背景: 接到上级指示,要从外网某库把数据全部导入到内网,数据每天更新一次即可,大约几百万条数据,两个库结构一样,mysql的,两台数据库所在服务器都是windows server的,写个java接口实 ...
- Serverless 的价值
作者 | 许晓斌 阿里云高级技术专家 本文整理自<Serverless 技术公开课>,关注"Serverless"公众号,回复 入门 ,即可获取 Serverless ...