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 ...
随机推荐
- border inset outset ,border-radius
1. 例子: div{ width:256px; height:256px; border: 10px inset #f00; margin:0 auto; border-radius:255px; ...
- php-fpm 启动 关闭 进程逃逸 pid
正常关闭失败 [root@d personas]# /etc/init.d/php-fpm stopGracefully shutting down php-fpm /etc/init.d/php-f ...
- Navicat for MySQL远程连接虚拟机
在虚拟机中进入mysql mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT O ...
- python并发之IO模型(一)
事件驱动模型 协程:遇到IO操作就切换. 但什么时候切回去呢?怎么确定IO操作完了? 很多程序员可能会考虑使用“线程池”或“连接池”.“线程池”旨在减少创建和销毁线程的频率,其维持一定合理数量的线程, ...
- 通过profile优化SQL语句
开启profile优化SQL语句:set profiling=1;执行SQL语句show profiles;show profile for query 2;//根据query_id 查看某个查询的详 ...
- 瑞丽熵(renyi entropy)
在信息论中,Rényi熵是Hartley熵,Shannon熵,碰撞熵和最小熵的推广.熵能量化了系统的多样性,不确定性或随机性.Rényi熵以AlfrédRényi命名.在分形维数估计的背景下,Rény ...
- deeplink
http://www.cnblogs.com/shadajin/p/5724117.html Deeplink,简单讲,就是你在手机上点击一个链接之后,可以直接链接到app内部的某个页面,而不是app ...
- Linux查看某个端口+gcc动态编译
Linux下就: 1.lsof -i:端口号 2.netstat -tunlp|grep 端口号 gcc:动态编译 gcc –fpic –c file.c –o file.o gcc –shared ...
- node拦截器设置
node的拦截器主要目的是用户登录的时候为用户存了一个session,用户登录后的其他操作都要经过拦截器,对比session的值,并把session的过期时间延长. 拦截器主要是在路由文件routes ...
- jQuery之DOM操作大全
jQuery属性操作 获取元素属性的语法:attr(name) 例子:$("#img1").attr("src"); 设置元素单个属性的语法:attr(key, ...