BZOJ 2752 [HAOI2012]高速公路(road):线段树【维护区间内子串和】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2752
题意:
有一个初始全为0的,长度为n的序列a。
有两种操作:
(1)C l r v: 将[l,r)内的数全部加v。
(2)Q l r: 在[l,r)内随机选两个数x,y(x < y),问你∑(a[x to y])的期望,用最简分数形式输出。
题解:
首先,题中要求的期望 = 区间内所有子串之和 / 区间内子串个数。
如果一个区间的长度为len,显然区间内的子串个数为len*(len+1)/2。
所以题目就变成了怎样维护区间内所有子串之和。
dat表示某个区间的子串和。
假设有两个相邻区间l,r,合并起来的区间叫x。
那么dat[x] = dat[x] + dat[y] + 跨两个区间的子串和
所以接下来考虑如何求跨区间的子串和。
sum表示某个区间的所有元素之和。
ln表示区间l的长度,rn表示区间r的长度。
ls表示某个区间的所有所有前缀之和,rs表示某个区间的所有后缀之和。
则跨区间的子串之和 = rs[l]*rn + ls[r]*ln
即dat[x] = dat[x] + dat[y] + rs[l]*rn + ls[r]*ln
ls,rs和sum的合并就很好求了:
ls[x] = ls[l] + rn*sum[l] + ls[r]
rs[x] = rs[r] + ln*sum[r] + rs[l]
sum[x] = sum[l] + sum[r]
这样线段树的pushup函数就写完了。
然后考虑如何pushdown传标记。
tag表示某个区间被同时加了多少。
现在只考虑当前节点x的某一个儿子y,儿子y的区间长度为len。
首先考虑tag[x]对dat[y]的贡献。
贡献 = 枚举子串的长度 * 这种长度的子串个数 * tag[x]
即:dat[y] += ∑ i*(len-i+1)*tag[x],其中i∈[1,len]。
化简得:dat[y] += ( len*(len+1)/2*(len+1) + ∑(i^2) ) * tag[x]
对于其中的∑(i^2),事先O(n)预处理出来一个平方前缀和数组sqr即可。
然后易得tag[x]对ls,rs,sum的贡献:
ls[y] += len*(len+1)/2*tag[x]
rs[y] += len*(len+1)/2*tag[x]
sum[y] += len*tag[x]
这样pushdown也就写好了。
然后大力线段树即可QAQ……
AC Code:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define MAX_N 100005
#define MAX_T 400005
#define int ll using namespace std; typedef long long ll; struct Node
{
int dt,ls,rs,s,ln;
Node(int _dt,int _ls,int _rs,int _s,int _ln)
{
dt=_dt; ls=_ls; rs=_rs; s=_s; ln=_ln;
}
Node(){}
friend Node mix(const Node &a,const Node &b)
{
int _dt=a.dt+b.dt+a.rs*b.ln+b.ls*a.ln;
int _ls=a.ls+b.ln*a.s+b.ls;
int _rs=b.rs+a.ln*b.s+a.rs;
int _s=a.s+b.s;
int _ln=a.ln+b.ln;
return Node(_dt,_ls,_rs,_s,_ln);
}
}; int n,m;
int ls[MAX_T];
int rs[MAX_T];
int dat[MAX_T];
int sum[MAX_T];
int tag[MAX_T];
int sqr[MAX_N]; void cal_sqr()
{
for(int i=;i<=n;i++) sqr[i]=sqr[i-]+i*i;
} void push_up(int x,int len)
{
int l=x*+,r=x*+;
Node L(dat[l],ls[l],rs[l],sum[l],len-(len>>));
Node R(dat[r],ls[r],rs[r],sum[r],(len>>));
Node tmp=mix(L,R);
dat[x]=tmp.dt;
ls[x]=tmp.ls;
rs[x]=tmp.rs;
sum[x]=tmp.s;
} void push_down(int x,int len)
{
if(tag[x])
{
int l=x*+,r=x*+;
int ln=(len-(len>>)),rn=(len>>);
dat[l]+=(ln*(ln+)/*(ln+)-sqr[ln])*tag[x];
dat[r]+=(rn*(rn+)/*(rn+)-sqr[rn])*tag[x];
ls[l]+=ln*(ln+)/*tag[x];
ls[r]+=rn*(rn+)/*tag[x];
rs[l]+=ln*(ln+)/*tag[x];
rs[r]+=rn*(rn+)/*tag[x];
sum[l]+=ln*tag[x];
sum[r]+=rn*tag[x];
tag[l]+=tag[x];
tag[r]+=tag[x];
tag[x]=;
}
} void update(int a,int b,int k,int l,int r,int x)
{
if(a<=l && r<=b)
{
int len=r-l+;
tag[k]+=x;
sum[k]+=len*x;
ls[k]+=len*(len+)/*x;
rs[k]+=len*(len+)/*x;
dat[k]+=(len*(len+)/*(len+)-sqr[len])*x;
return;
}
if(r<a || b<l) return;
push_down(k,r-l+);
int mid=(l+r)>>;
update(a,b,k*+,l,mid,x);
update(a,b,k*+,mid+,r,x);
push_up(k,r-l+);
} Node query(int a,int b,int k,int l,int r)
{
if(a<=l && r<=b) return Node(dat[k],ls[k],rs[k],sum[k],r-l+);
if(r<a || b<l) return Node(,,,,);
push_down(k,r-l+);
int mid=(l+r)>>;
Node v1=query(a,b,k*+,l,mid);
Node v2=query(a,b,k*+,mid+,r);
return mix(v1,v2);
} signed main()
{
scanf("%lld%lld",&n,&m);
n--;
cal_sqr();
char opt[];
int l,r,v;
while(m--)
{
scanf("%s%lld%lld",opt,&l,&r);
if(opt[]=='C')
{
scanf("%lld",&v);
update(l,r-,,,n,v);
}
else
{
int dt=query(l,r-,,,n).dt;
int len=r-l;
int tot=len*(len+)/;
int g=__gcd(dt,tot);
printf("%lld/%lld\n",dt/g,tot/g);
}
}
}
BZOJ 2752 [HAOI2012]高速公路(road):线段树【维护区间内子串和】的更多相关文章
- BZOJ 2752: [HAOI2012]高速公路(road)( 线段树 )
对于询问[L, R], 我们直接考虑每个p(L≤p≤R)的贡献,可以得到 然后化简一下得到 这样就可以很方便地用线段树, 维护一个p, p*vp, p*(p+1)*vp就可以了 ----------- ...
- BZOJ 2752: [HAOI2012]高速公路(road) [线段树 期望]
2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1219 Solved: 446[Submit] ...
- bzoj 2752: [HAOI2012]高速公路(road)
Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收 ...
- ●BZOJ 2752 [HAOI2012]高速公路(road)
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2752题解: 期望,线段树. 把每个路段看成一个点,那么对于l~R的操作,就可以转化为对l~r ...
- BZOJ2752: [HAOI2012]高速公路(road)(线段树 期望)
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1820 Solved: 736[Submit][Status][Discuss] Descripti ...
- 【bzoj2752】[HAOI2012]高速公路(road) 线段树
题目描述 Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收费站组成的东西 ...
- 【GDKOI2016Day1T1-魔卡少女】【拆位】线段树维护区间内所有连续子区间的异或和
题意:给出N个数,M个操作.操作有修改和询问两种,每次修改将一个数改成另一个数,每次询问一个区间的所有连续子区间的异或和.n,m<=100000,ai<=1000 题解: 当年(其实也就是 ...
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- Can you answer these queries V SPOJ - GSS5 (分类讨论+线段树维护区间最大子段和)
recursion有一个整数序列a[n].现在recursion有m次询问,每次她想知道Max { A[i]+A[i+1]+...+A[j] ; x1 <= i <= y1 , x2 &l ...
随机推荐
- Springboot中读取自定义名称properties的
Springboot读取自定义的配置文件时候,使用@value,一定要指定配置文件的位置! 否则报错参数化异常!
- 使用 mock 测试
参考文章:https://semaphoreci.com/community/tutorials/getting-started-with-mocking-in-python What are the ...
- float 的先后顺序 理解流
<!DOCTYPE html><html><head><style> p{float:right;}</style></head> ...
- Service Name Port Number Transport Protocol tcp udp 端口号16bit
https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol The DHCP employs a connectionless ...
- Python3.6全栈开发实例[025]
25.文件a1.txt内容(升级题)name:apple price:10 amount:3 year:2012name:tesla price:100000 amount:1 year:2013通过 ...
- Android 屏幕适配扫盲、教程
转载请注明出处:http://blog.csdn.net/my_truelove/article/details/66584865 訪问 ruicb.com,一键抵达我的博客! 扫描左側或右下方二维码 ...
- sql语句备份/导入 mysql数据库或表命令
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qq1355541448/article/details/30049851
- PyNest——part 2: populations of neurons
part 2: populations of neurons introduction 在这篇讲义中,我们着眼于创建和参数化神经元批次,并将它们连接起来. 当你完成这些材料时,你会知道如何: 创建具有 ...
- MongoDB学习笔记—windows下安装
1.登录官网下载安装包 官网下载地址:https://www.mongodb.com/download-center?jmp=nav#community 根据你的系统下载 32 位或 64 位的 .m ...
- Vim 指令一览表
vim 程序编辑器 移动光标的方法 h 或 向左箭头键(←) 光标向左移动一个字符 j 或 向下箭头键(↓) 光标向下移动一个字符 k 或 向上箭头键(↑) 光标向上移动一个字符 l 或 向右箭头键( ...