题目https://www.luogu.org/problemnew/show/P2221

题意:有n个节点排成一条链,相邻节点之间有一条路。

C u v val表示从u到v的路径上的每条边权值都加val。

Q l r表示在l到r中等概率选择两个城市的路径长度的期望值。

思路:首先期望值的分子肯定是可以选择的方案数也就是$C^2_{r - l + 1}$

分子应该是所有可能的路径和。我们可以通过计算每一条边算了多少次得到。

对于第$i$条边,他的左端点有$(i - l + 1)$种可能,右端点有$(r - i + 1)$种可能。因此这$(i - l + 1)*(r - i + 1)$种路径都包含第$i$条边

所以分子可以表示为$\sum_{l}^{r}(i-l+1)*(r - i + 1) * a[i]$

把含$i$的和不含的都分离出来。可以变为$(r - l + 1-r*l)\sum a[i] + (r + l)\sum i *a[i] - \sum i^2*a[i]$

分别用线段树维护$\sum a[i], \sum i * a[i], \sum i^2 * a[i]$

小trick是$i$和$i^2$之和也可以保存在线段树节点中,维护起来比较方便。

 #include<cstdio>
#include<cstdlib>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stack>
#include<queue>
#include<iostream> #define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef pair<int, int> pr; int n, m;
const int maxn = 1e5 + ;
struct node{
LL i, a, ia, ii, iia, lazy;
}tree[maxn * ]; void build(int rt, int l, int r)
{
if(l == r){
tree[rt].i = l;
tree[rt].ii = 1ll * l * l;
return;
}
int mid = (l + r) / ;
build(rt << , l, mid);
build(rt << | , mid + , r);
tree[rt].i = tree[rt << ].i + tree[rt << | ].i;
tree[rt].ii = tree[rt << ].ii + tree[rt << | ].ii;
} void pushdown(int rt, int l, int r)
{
if(tree[rt].lazy){
tree[rt << ].lazy += tree[rt].lazy;
tree[rt << | ].lazy += tree[rt].lazy;
int mid = (l + r) / ;
tree[rt << ].a += 1ll * tree[rt].lazy * (mid - l + );
tree[rt << | ].a += 1ll * tree[rt].lazy * (r - mid);
tree[rt << ].ia += 1ll * tree[rt].lazy * tree[rt << ].i;
tree[rt << |].ia += 1ll * tree[rt].lazy * tree[rt << |].i;
tree[rt << ].iia += 1ll * tree[rt].lazy * tree[rt << ].ii;
tree[rt << |].iia += 1ll * tree[rt].lazy * tree[rt << |].ii;
tree[rt].lazy = ;
} } void pushup(int rt)
{
tree[rt].a = tree[rt << ].a + tree[rt << |].a;
tree[rt].ia = tree[rt << ].ia + tree[rt << | ].ia;
tree[rt].iia = tree[rt << ].iia + tree[rt << | ].iia;
} void update(int L, int R, int l, int r, int rt, int val)
{
if(L <= l && R >= r){
tree[rt].a += 1ll * val * (r - l + );
tree[rt].ia += 1ll * val * tree[rt].i;
tree[rt].iia += 1ll * val * tree[rt].ii;
tree[rt].lazy += val;
return;
}
pushdown(rt, l, r);
int mid = (l + r) / ;
if(L <= mid)update(L, R, l, mid, rt << , val);
if(R > mid)update(L, R, mid + , r, rt << | , val);
pushup(rt);
} LL sum1, sum2, sum3;
void query(int L, int R, int l, int r, int rt)
{
if(L <= l && R >= r){
sum1 += tree[rt].a;
sum2 += tree[rt].ia;
sum3 += tree[rt].iia;
return;
}
pushdown(rt, l, r);
int mid = (l + r) / ;
if(L <= mid)query(L, R, l, mid, rt << );
if(R > mid)query(L, R, mid + , r, rt << | ); } LL gcd(LL a, LL b)
{
if(!b)return a;
else return gcd(b, a % b);
}
int main()
{
scanf("%d%d", &n, &m);
build(, , n - );
for(int i = ; i < m; i++){
string type;
int l, r;
cin>>type>>l>>r; r--;
if(type[] == 'C'){
int val;
scanf("%d", &val);
update(l, r, , n - , , val);
}
else{
sum1 = sum2 = sum3 = ;
query(l, r, , n - , );
LL fac = (1ll * r - l + - 1ll * r * l) * sum1 + (r + l) * sum2 - sum3;
LL div = 1ll * (r - l + ) * (r - l + ) / ;
// cout<<sum1<<" "<<sum2<<" "<<sum3<<endl;
// cout<<fac<<" "<<div<<endl;
LL g = gcd(fac, div);
fac /= g;
div /= g;
printf("%lld/%lld\n", fac, div);
}
}
return ;
}

洛谷P2221 高速公路【线段树】的更多相关文章

  1. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

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

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

  3. 【洛谷】【线段树】P1047 校门外的树

    [题目描述:] 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,……,L ...

  4. 【洛谷】【线段树】P1886 滑动窗口

    [题目描述:] 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. [输入格式:] 输入一共 ...

  5. 【洛谷】【线段树】P3353 在你窗外闪耀的星星

    [题目描述:] /* 飞逝的的时光不会模糊我对你的记忆.难以相信从我第一次见到你以来已经过去了3年.我仍然还生动地记得,3年前,在美丽的集美中学,从我看到你微笑着走出教室,你将头向后仰,柔和的晚霞照耀 ...

  6. 洛谷P5280 [ZJOI2019]线段树

      https://www.luogu.org/problemnew/show/P5280 省选的时候后一半时间开这题,想了接近两个小时的各种假做法,之后想的做法已经接近正解了,但是有一些细节问题理不 ...

  7. 洛谷 - P1198 - 最大数 - 线段树

    https://www.luogu.org/problemnew/show/P1198 要问区间最大值,肯定是要用线段树的,不能用树状数组.(因为没有逆元?但是题目求的是最后一段,可以改成类似前缀和啊 ...

  8. 洛谷P3374(线段树)(询问区间和,支持单点修改)

    洛谷P3374 //询问区间和,支持单点修改 #include <cstdio> using namespace std; ; struct treetype { int l,r,sum; ...

  9. 洛谷 P2391 白雪皑皑 线段树+优化

    题目描述: 现在有 \(N\) 片雪花排成一列. Pty 要对雪花进行$ M $次染色操作,第 \(i\)次染色操作中,把\((i*p+q)%N+1\) 片雪花和第\((i*q+p)%N+1\)片雪花 ...

随机推荐

  1. 关于tomcat9的startup.bat闪退问题&乱码

    1.打开apache-tomcat-9.0.22的bin目录  选择图中文件  记事本打开 2.更改文件 setclasspath.bat .0_172\jre 3.保存  startup ----- ...

  2. 公钥、私钥、数字签名、数字证书、对称与非对称算法、HTTPS

    作者: yoyoso https://my.oschina.net/ioslighter/blog/359207 对公钥和私钥有点稀里糊涂的,搜索了一些资料,作一些整理吧,先看这个: 加密--公钥 看 ...

  3. Android--DES加密

    Base64.java import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputS ...

  4. Lucene入门+实现

    Lucene简介详情见:(https://blog.csdn.net/Regan_Hoo/article/details/78802897) lucene实现原理 其实网上很多资料表明了,lucene ...

  5. [Luogu5324][BJOI2019]删数(线段树)

    CF风格题,先猜结论,记数列中i这个数共出现了cnt[i]次,那么所有区间[i-cnt[i]+1,i]的并集的补集大小就是答案. 于是我们只需要线段树维护每个位置是否被某个区间覆盖到即可,对于整体加减 ...

  6. Python虚拟环境virtualenv的安装与使用详解(转)

    virtualenv参考:https://www.jb51.net/article/114933.htm virtualenvwrapper参考:https://www.jianshu.com/p/7 ...

  7. 【转发】Java split()用法

    特殊情况有 * ^ : | . \ 一.单个符号作为分隔符  String address="上海\上海市|闵行区\吴中路"; String[] splitAddress=addr ...

  8. NRF52832 Mesh SDK 调试记录

    1.Mesh SDK模型,Node节点在重启之后,心跳不能正常保持,即无法在次启动心跳的解决办法: 原因:主要是因为相关模型没有从Flash里面读取所致,因此只需要回复保存配置即可. 关键代码如下: ...

  9. java中对List中的元素进行排序

    Collections对List集合中的数据进行排序 有时候需要对集合中的元素按照一定的规则进行排序,这就需要用到 Java中提供的对集合进行操作的工具类Collections,其中的sort方法 N ...

  10. 3_PHP表达式_3_有关变量或常量状态的函数

    以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. 1. 数据类型查看函数 PHP为变量或常量提供了查看数据类型的函数,其中包括gettype()和var_dump( ...