[Luogu 2221] HAOI2012 高速公路

<题目链接>


比较容易看出的线段树题目。

由于等概率,期望便转化为 子集元素和/子集个数。

每一段l..r中,子集元素和为:

\(\sum w_{i}(i-l+1)(r-i)\) //\((i-l+1)(r-i)\)是每个数用到的次数

\(=\sum w_{i}((r-lr)+(l+r-1)i-i^{2})\)

\(=(r-lr)\sum w_{i}+(l+r-1)\sum i\times w_{i}-\sum i^{2}\times w_{i}\)

由此观之,线段树需要维护\(\sum w_{i}\)v[0]、\(\sum i\times w_{i}\)v[1]、\(\sum i^{2}\times w_{i}\)v[2]

有这样一个神奇的公式:

\(1^{2}+2^{2}+\dots+n^{2}=n(n+1)(2n+1)/6\)

所以,在进行Update操作时,设size=r-l+1,改变量为v

v[0]+=v*size;
v[1]+=v*size*(l+r)>>1;
v[2]+=v*(r*(r+1)*((r<<1)+1)-(l-1)*l*((l<<1)-1))/6LL;

记得开long long以及各种强制转int为long long!隐式类型转换简直天坑。

线段树基础不扎实的我这题调了一天…

#include <cstdio>
#include <cstring>
const int MAXN=100010;
int n,m;
class SegmentTree
{
public:
SegmentTree(void)
{
memset(s,0,sizeof s);
}
void BuildTree(int i,int l,int r)
{
s[i].l=l,s[i].r=r;
if(l==r)
return;
int j=i<<1,mid=l+r>>1;
BuildTree(j,l,mid),BuildTree(j+1,mid+1,r);
}
void Add(int i,int l,int r,long long v)
{
if(l==s[i].l && r==s[i].r)
{
Update(i,v);
return;
}
if(s[i].l!=s[i].r && s[i].lazy)
PushDown(i);
int j=i<<1,mid=s[i].l+s[i].r>>1;
if(r<=mid)
Add(j,l,r,v);
else if(l>mid)
Add(j+1,l,r,v);
else
Add(j,l,mid,v),Add(j+1,mid+1,r,v);
PushUp(i);
}
void Ans(long long l,long long r)
{
long long t,ans,cnt=(r-l+1)*(r-l)>>1LL,sum[3];
for(int i=0;i<3;++i)
sum[i]=Sum(1,l,r-1,i);
ans=sum[0]*(r-l*r)+sum[1]*(l+r-1)-sum[2];
t=GCD(ans,cnt);
printf("%lld/%lld\n",ans/t,cnt/t);
}
private:
struct node
{
int l,r;
long long lazy,v[3];
}s[MAXN<<2];
long long GCD(long long x,long long y)
{
return !y ? x : GCD(y,x%y);
}
void Update(int i,long long v)
{
long long l=s[i].l,r=s[i].r,size=r-l+1;
s[i].lazy+=v;
s[i].v[0]+=v*size;
s[i].v[1]+=v*size*(l+r)>>1;
s[i].v[2]+=v*(r*(r+1)*((r<<1)+1)-(l-1)*l*((l<<1)-1))/6LL;
}
void PushUp(int i)
{
for(int j=0;j<3;++j)
s[i].v[j]=s[i<<1].v[j]+s[i<<1|1].v[j];
}
void PushDown(int i)
{
int j=i<<1;
Update(j,s[i].lazy),Update(j+1,s[i].lazy);
s[i].lazy=0;
}
long long Sum(int i,int l,int r,int k)
{
if(l==s[i].l && r==s[i].r)
return s[i].v[k];
if(s[i].l!=s[i].r && s[i].lazy)
PushDown(i);
int j=i<<1,mid=s[i].l+s[i].r>>1;
if(r<=mid)
return Sum(j,l,r,k);
else if(l>mid)
return Sum(j+1,l,r,k);
else
return Sum(j,l,mid,k)+Sum(j+1,mid+1,r,k);
}
}T;
int main(int argc,char *argv[])
{
scanf("%d %d",&n,&m);
T.BuildTree(1,1,n-1);
for(int i=1,l,r,v;i<=m;++i)
{
char c;
scanf("\n%c %d %d",&c,&l,&r);
if(c=='C')
{
scanf("%d",&v);
T.Add(1,l,r-1,v);
}
else
T.Ans(l,r);
}
return 0;
}

谢谢阅读。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    [HAOI2012]高速公路(road) Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y ...

  9. 【BZOJ2752】【Luogu P2221】 [HAOI2012]高速公路

    不是很难的一个题目.正确思路是统计每一条边被经过的次数,但我最初由于习惯直接先上了一个前缀和再推的式子,导致极其麻烦难以写对而且会爆\(longlong\). 推导过程请看这里. #include & ...

随机推荐

  1. C语言中的字符串分割函数

    char *strtok(char *s, const char *delim); 分解字符串为一组字符串.s为要分解的字符串,delim为分隔符字符串. 从s开头开始的一个个被分割的串.当没有被分割 ...

  2. js设计模式之代理模式以及订阅发布模式

    为啥将两种模式放在一起呢?因为这样文章比较长啊. 写博客的目的我觉得首要目的是整理自己的知识点,进而优化个人所得知识体系.知识成为个人的知识,就在于能够用自己的话表达同一种意义. 本文是设计模式系列文 ...

  3. 修改QQ各版本的默认保存位置(聊天记录)

    这几天没少折腾windows,都有点烦了,我是那种有强迫症的,只要知道的自己没有做到的会感觉到浑身不爽的因为系统重装了好几次,QQ也没少安装几次,我使用的是TM的QQ(没有 那么多烦人的广告,娱乐组件 ...

  4. android异常Unable to instantiate activity ComponentInfo解决方法

    我是下面提到的第四条: 在Order and Export 中 把新加的 android-support-v4.jar的前面的对号打上勾 保存:就可以了: 做android开发的可能都碰到" ...

  5. 【数据库】】MySQL之desc查看表结构的详细信息

    在mysql中如果想要查看表的定义的话:有如下方式可供选择 1.show create table 语句: show create table table_name; 2.desc table_nam ...

  6. 【】Python】异常处理try...except、raise

    一.try...except 有时候我们写程序的时候,会出现一些错误或异常,导致程序终止.例如,做除法时,除数为0,会引起一个ZeroDivisionError 例子: 1 2 3 4 a=10 b= ...

  7. c# 日志记录 行号

    Console.WriteLine(ex.Message); //通过如下代码来记录异常详细的信息 ); Console.WriteLine("文件名:{0},行号:{1},列号:{2}&q ...

  8. 【题解】APIO2018 Duathlon 铁人两项

    首先对于给出的图建立圆方树,然后我们分类讨论每一个点作为中间的中转站出现的情况有多少种,累积到 \(ans\) 中. 对于圆点:在任意两个子树内分别选出一个节点都是合法的. 对于方点:连接向方点的点均 ...

  9. bzoj3489: A simple rmq problem (主席树)

    //========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/  转载要声明! //=============== ...

  10. POJ2689:Prime Distance——题解

    http://poj.org/problem?id=2689 题目大意,给不超过int的l,r,其中r-l+1<=1000000,筛出其中的素数,并且求出相邻素数差值最大和最小的一对. ———— ...