思路

考虑每一条边的贡献,然后推式子

\[\begin{align}&\sum_{i}V_i\times(R-i+1)\times(i-L+1)\\=&\sum_{i}V_i\left[(Ri-i^2+i)-(RL-iL+L)+(R-i+1)\right]\\=&\sum_{i}V_i\left[Ri-i^2+i-RL+Li-L+R-i+1\right]\\=&\sum_{i}Vi\left[(Ri+Li)-i^2-RL+(R-L+1)\right]\\=&\sum_{i}(Ri+Li)V_i-\sum_{i}i^2V_i-\sum_{i}RLV_i+\sum_{i}(R-L+1)V_i\\=&(R+L)\sum_{i}iVi-\sum_{i}i^2V_i-RL\sum_{i}V_i+(R-L+1)\sum_{i}V_i\\=&(R+L)\sum_iiV_i-\sum_ii^2V_i+(R-L+1-RL)\sum_{i}V_i\end{align}
\]

然后用线段树维护就好了

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
const int MAXN = 100100;
namespace Seg1{//v_i
int seg[MAXN<<2]={},tag[MAXN<<2]={};
void pushup(int o){
seg[o]=seg[o<<1]+seg[o<<1|1];
}
void build(int l,int r,int o,int *a){
if(l==r){
seg[o]=a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,o<<1,a);
build(mid+1,r,o<<1|1,a);
pushup(o);
}
void pushdown(int o,int ln,int rn){
if(tag[o]){
seg[o<<1]+=tag[o]*ln;
seg[o<<1|1]+=tag[o]*rn;
tag[o<<1]+=tag[o];
tag[o<<1|1]+=tag[o];
tag[o]=0;
}
}
void add(int L,int R,int l,int r,int o,int c){
if(L<=l&&r<=R){
seg[o]+=c*(r-l+1);
tag[o]+=c;
return;
}
int mid=(l+r)>>1;
pushdown(o,mid-l+1,r-mid);
if(L<=mid)
add(L,R,l,mid,o<<1,c);
if(R>mid)
add(L,R,mid+1,r,o<<1|1,c);
pushup(o);
}
int query(int L,int R,int l,int r,int o){
if(L<=l&&r<=R){
return seg[o];
}
int mid=(l+r)>>1,ans=0;
pushdown(o,mid-l+1,r-mid);
if(L<=mid)
ans+=query(L,R,l,mid,o<<1);
if(R>mid)
ans+=query(L,R,mid+1,r,o<<1|1);
return ans;
}
};
namespace Seg2{//v_i*i
int seg[MAXN<<2]={},tag[MAXN<<2]={};
int sum(int l,int r){
return (l+r)*(r-l+1)/2;
}
void pushup(int o){
seg[o]=seg[o<<1]+seg[o<<1|1];
}
void build(int l,int r,int o,int *a){
if(l==r){
seg[o]=a[l]*l;
return;
}
int mid=(l+r)>>1;
build(l,mid,o<<1,a);
build(mid+1,r,o<<1|1,a);
pushup(o);
}
void pushdown(int o,int lx,int rx){
if(tag[o]){
int mid=(lx+rx)>>1;
seg[o<<1]+=tag[o]*sum(lx,mid);
seg[o<<1|1]+=tag[o]*sum(mid+1,rx);
tag[o<<1]+=tag[o];
tag[o<<1|1]+=tag[o];
tag[o]=0;
}
}
void add(int L,int R,int l,int r,int o,int c){
if(L<=l&&r<=R){
seg[o]+=c*sum(l,r);
tag[o]+=c;
return;
}
int mid=(l+r)>>1;
pushdown(o,l,r);
if(L<=mid)
add(L,R,l,mid,o<<1,c);
if(R>mid)
add(L,R,mid+1,r,o<<1|1,c);
pushup(o);
}
int query(int L,int R,int l,int r,int o){
if(L<=l&&r<=R){
return seg[o];
}
int mid=(l+r)>>1,ans=0;
pushdown(o,l,r);
if(L<=mid)
ans+=query(L,R,l,mid,o<<1);
if(R>mid)
ans+=query(L,R,mid+1,r,o<<1|1);
return ans;
}
};
namespace Seg3{//vi*i^2
int seg[MAXN<<2]={},tag[MAXN<<2]={};
void pushup(int o){
seg[o]=seg[o<<1]+seg[o<<1|1];
}
int f(int x){
return (2*x+1)*(x+1)*x/6;
}
int sum(int l,int r){
return f(r)-f(l-1);
}
void build(int l,int r,int o,int *a){
if(l==r){
seg[o]=a[l]*l*l;
return;
}
int mid=(l+r)>>1;
build(l,mid,o<<1,a);
build(mid+1,r,o<<1|1,a);
pushup(o);
}
void pushdown(int o,int lx,int rx){
if(tag[o]){
int mid=(lx+rx)>>1;
seg[o<<1]+=tag[o]*sum(lx,mid);
seg[o<<1|1]+=tag[o]*sum(mid+1,rx);
tag[o<<1]+=tag[o];
tag[o<<1|1]+=tag[o];
tag[o]=0;
}
}
void add(int L,int R,int l,int r,int o,int c){
if(L<=l&&r<=R){
seg[o]+=c*sum(l,r);
tag[o]+=c;
return;
}
int mid=(l+r)>>1;
pushdown(o,l,r);
if(L<=mid)
add(L,R,l,mid,o<<1,c);
if(R>mid)
add(L,R,mid+1,r,o<<1|1,c);
pushup(o);
}
int query(int L,int R,int l,int r,int o){
if(L<=l&&r<=R){
return seg[o];
}
int mid=(l+r)>>1,ans=0;
pushdown(o,l,r);
if(L<=mid)
ans+=query(L,R,l,mid,o<<1);
if(R>mid)
ans+=query(L,R,mid+1,r,o<<1|1);
return ans;
}
void debug(int l,int r,int o){
printf("%lld %lld %lld %lld %lld\n",l,r,o,seg[o],tag[o]);
if(l==r)
return;
int mid=(l+r)>>1;
debug(l,mid,o<<1);
debug(mid+1,r,o<<1|1);
}
};
int gcd(int a,int b){
return (b==0)?a:gcd(b,a%b);
}
int a[MAXN]={0},n,m;
using namespace Seg1;
using namespace Seg2;
using namespace Seg3;
signed main(){
scanf("%lld %lld",&n,&m);
n--;
Seg1::build(1,n,1,a);
Seg2::build(1,n,1,a);
Seg3::build(1,n,1,a);
for(int i=1;i<=m;i++){
char c=getchar();
while(c!='C'&&c!='Q')
c=getchar();
if(c=='C'){
int l,r,val;
scanf("%lld %lld %lld",&l,&r,&val);
r--;
Seg1::add(l,r,1,n,1,val);
Seg2::add(l,r,1,n,1,val);
Seg3::add(l,r,1,n,1,val);
//Seg3::debug(1,n,1);
}
else{
int l,r;
scanf("%lld %lld",&l,&r);
r--;
int sum1=Seg1::query(l,r,1,n,1);
int sum2=Seg2::query(l,r,1,n,1);
int sum3=Seg3::query(l,r,1,n,1);
//Seg3::debug(1,n,1);
int ans=sum1*(r-l+1-r*l)+(r+l)*sum2-sum3;
// printf("sum1=%lld sum2=%lld sum3=%lld %lld\n",sum1,sum2,sum3,ans);
int t=(r-l+1)*(r-l+2)/2;
int Gcd=gcd(t,ans);
printf("%lld/%lld\n",ans/Gcd,t/Gcd); }
}
return 0;
}

P2221 [HAOI2012]高速公路的更多相关文章

  1. P2221 [HAOI2012]高速公路(线段树)

    P2221 [HAOI2012]高速公路 显然答案为 $\dfrac{\sum_{i=l}^r\sum_{j=l}^{r}dis[i][j]}{C_{r-l+1}^2}$ 下面倒是挺好算,组合数瞎搞 ...

  2. 洛谷 P2221 [HAOI2012]高速公路

    链接: P2221 题意: 有 \(n(1\leq n\leq 10^5)\) 个点,从第 \(i(1\leq i< n)\) 个点向第 \(i+1\) 个点连有边.最初所有边长 \(v_i\) ...

  3. 洛谷P2221 [HAOI2012]高速公路

    线段树 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> ...

  4. 【题解】Luogu P2221 [HAOI2012]高速公路

    原题传送门 这道题还算简单 我们要求的期望值: \[\frac{\sum_{i=l}^r\sum_{j=l}^rdis[i][j]}{C_{r-l+1}^{2}}\] 当然是上下两部分分别求,下面肥肠 ...

  5. 洛谷P2221 [HAOI2012]高速公路(线段树+概率期望)

    传送门 首先,答案等于$$ans=\sum_{i=l}^r\sum_{j=i}^r\frac{sum(i,j)}{C_{r-l+1}^2}$$ 也就是说所有情况的和除以总的情况数 因为这是一条链,我们 ...

  6. luogu P2221 [HAOI2012]高速公路题解

    题面 很套路的拆式子然后线段树上维护区间和的题.一般都是把式子拆成区间内几个形如\(\sum i*a_i, \sum i^2 * a_i\)的式子相加减的形式. 考虑一次询问[l,r]的答案怎么算: ...

  7. BZOJ2752: [HAOI2012]高速公路(road)

    2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 608  Solved: 199[Submit][ ...

  8. BZOJ 2752: [HAOI2012]高速公路(road)( 线段树 )

    对于询问[L, R], 我们直接考虑每个p(L≤p≤R)的贡献,可以得到 然后化简一下得到 这样就可以很方便地用线段树, 维护一个p, p*vp, p*(p+1)*vp就可以了 ----------- ...

  9. 【线段树】BZOJ2752: [HAOI2012]高速公路(road)

    2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1621  Solved: 627[Submit] ...

随机推荐

  1. STL之Set和multiset容器

    1.Set和multiset容器 1)set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指定插入位置. 2)set采用红黑树变体的数据 ...

  2. 【转】Loadrunner 性能指标定位系统瓶颈

    转至:http://www.51testing.com/html/63/n-1224463.html Loadrunner 性能指标定位系统瓶颈 判断CPU瓶颈 1, %processor time ...

  3. 排序(Sort)-----选择排序

       声明:文中动画转载自https://blog.csdn.net/qq_34374664/article/details/79545940    1.选择排序简介 选择排序(Select Sort ...

  4. Azure IoT 技术研究系列2-设备注册到Azure IoT Hub

    上篇博文中,我们主要介绍了Azure IoT Hub的基本概念.架构.特性: Azure IoT 技术研究系列1-入门篇 本文中,我们继续深入研究,做一个起步示例程序:模拟设备注册到Azure IoT ...

  5. 【Hive学习之三】Hive 函数

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 apache-hive-3.1.1 ...

  6. Spring源码阅读(七)

    这一讲主要分析bean注册过程中各种初始化方法回调的执行逻辑(initializeBean) /** * Initialize the given bean instance, applying fa ...

  7. Spring Batch 远程分区和远程分块的区别

    Partitioning is a master/slave step configuration that allows for partitions of data to be processed ...

  8. javanio2

    package com.lanhuigu.nio.selector; import java.net.InetSocketAddress; import java.nio.ByteBuffer; im ...

  9. 51nod 1057 N的阶乘 (大数运算)

    输入N求N的阶乘的准确值.   Input 输入N(1 <= N <= 10000) Output 输出N的阶乘 Input示例 5 Output示例 120 压位: 每个数组元素存多位数 ...

  10. bzoj4445 小凸想跑步

    题目链接 半平面交,注意直线方向!!! 对于凸包上任意一条边$LINE(p_i,p_{i+1})$都有$S_{\Delta{p_i} {p_{i + 1}}p} < S_{\Delta{p_0} ...