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 ...
随机推荐
- 2048 worker_connections are not enough while connecting to upstream
2048 worker_connections are not enough while connecting to upstream http://mailman.nginx.org/piperma ...
- Quality of service
w https://en.wikipedia.org/wiki/Quality_of_service Quality of service (QoS) is the overall performan ...
- <2013 08 12> Andrew:C语言的一点心得
C语言的特点在于,这是少见的中级语言(介于机器汇编和高级语言之间),因此它极其紧密地与特定机器架构.编译器.操作系统.库等基本概念相连.在底层,人们可以少量的甚至不使用汇编,但是不能不使用C.它以一种 ...
- VMware虚拟机不能联网的解决办法
Linux安装的centos系统,不能正常连接网络 1.编辑config文件 [root@localhost ~]# cd /etc/selinux [root@localhost selinux]# ...
- Java8 FutureTask 分析
实现FutureTask的要点 1.需要实现一个链表(每个节点包含当前线程的引用) 2.通过LockSupport.park 对线程进行阻塞 3.节点的唤醒(task完成, 线程Interrupt, ...
- 解决后台无法进入提示DedeCMS Error: (PHP 5.3 and above) Please set 'request_order' ini value
最近小美眉的网站被盯上了,被添加了非常多的dubo页面,删除了5w多个文件,但还是不停的增加,因为网站权重还可以,很多都被收录了,结果可想而知,ytkah帮她迁移,在迁移网站时遇到了一些问题,后台登录 ...
- 0405-服务注册与发现-客户端负载均衡-Ribbon 同Eureka使用,Ribbon脱离Eureka使用
一.Ribbon 同Eureka使用,注意事项 前几节一同使用,注意事项: 如果没有其他区域数据源,则根据客户端配置进行猜测(与实例配置相反).能够获取eureka.client.availabili ...
- Simple Tips for Collection in Python
I believe that the following Python code is really not hard to understand. But I think we should use ...
- (C#)ListView双击Item事件
/// <summary> /// 双击选择播放列表项进行播放 /// </summary> /// <param name="sender"> ...
- webbrowser控件——Windows下的开发利器
首先说明,本人比较菜,做C++没多长时间. 刚开始用MFC写程序时,连个基本的字体都不会变(颜色.大小等), 索性干脆就啥也不改了,直接默认,界面就那样了,老子不管了. 心想这C++做个界面咋就那么麻 ...