bzoj-2752 高速公路 road

题意:

给出一个n个结点,n-1条边的链,边权初始为0;

m次操作,操作有两种:

1. C:区间[l,r]的边权加上或减去一个数;

2. Q:查询区间随机取不相同两点之间的期望长度;

题解:

区间加减之类的东西显然是线段树的应用,恰巧这道题就在链上;

主要这题还是维护第二问的东西;

区间[l,r]的选路方式共有(r-l+1)*(r-l)/2这些种,那么只要求出所有路径总长度就好了;

对每一条路x来考虑的话,这条路被选的条件是同时选了左面的点和右面的点;

假设这条路的权值是val[x],那么这条路对答案的贡献就是 左面点数*右面点数*val[x];

问题在于如何用线段树实现对此的向上/向下更新;

向下更新的话,长度为n的区间所有数同时减去一个v的话,答案会变化 v*n(n+1)(n+2)/6 这个值;

其实就是1*4+2*3+3*2+4*1这东西的求和公式= =

而向上更新则是两个区间的合并,对每条路考虑左右增加的点数;

那左区间所有路其实都是在右面增加了 右面路径数 这样多的点;

对答案的影响就是 1*val[1]+2*val[2]+3*val[3]... 再乘一个点数;

那么设这东西为L,利用区间和也可以快速维护这东西;

右区间同理,维护R处理就可以了;

query函数有些糟糕,因为需要向上传四个参数,还要搞一个合并;

然后我比较懒所以直接用pair乱搞。。那段区间合并看着就蛮高能的。。

long long没开够WA了一发,全改成long long就A了;

具体原因不查了= =反正这东西似乎不重要?

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 140142
#define pr pair<ll,ll>
#define par pair<pr,pr>
#define lson l,mid,no<<1
#define rson mid+1,r,no<<1|1
using namespace std;
typedef long long ll;
ll sum[N<<2],ans[N<<2],L[N<<2],R[N<<2],cov[N<<2];
char str[10];
ll gcd(ll a,ll b)
{
	ll t=a%b;
	while(t)
	{
		a=b,b=t;
		t=a%b;
	}
	return b;
}
void Pushup(ll no,ll len)
{
	sum[no]=sum[no<<1]+sum[no<<1|1];
	L[no]=L[no<<1]+L[no<<1|1]+sum[no<<1|1]*(len-(len>>1));
	R[no]=R[no<<1]+R[no<<1|1]+sum[no<<1]*(len>>1);
	ans[no]=ans[no<<1]+ans[no<<1|1]+L[no<<1]*(len>>1)+R[no<<1|1]*(len-(len>>1));
}
void change(ll no,ll v,ll n)
{
	cov[no]+=v;
	sum[no]+=v*n;
	L[no]+=n*(n+1)/2*v;
	R[no]+=n*(n+1)/2*v;
	ans[no]+=n*(n+1)*(n+2)/6*v;
}
void Pushdown(ll no,ll len)
{
	if(cov[no])
	{
		change(no<<1,cov[no],len-(len>>1));
		change(no<<1|1,cov[no],len>>1);
		cov[no]=0;
	}
}
void update(ll l,ll r,ll no,ll st,ll en,ll val)
{
	if(st<=l&&r<=en)
		change(no,val,r-l+1);
	else
	{
		ll mid=l+r>>1;
		Pushdown(no,r-l+1);
		if(en<=mid)		update(lson,st,en,val);
		else if(st>mid)	update(rson,st,en,val);
		else	update(lson,st,en,val),update(rson,st,en,val);
		Pushup(no,r-l+1);
	}
}
par query(ll l,ll r,ll no,ll st,ll en)
{
	if(st<=l&&r<=en)
		return par(pr(ans[no],sum[no]),pr(L[no],R[no]));
	else
	{
		ll mid=l+r>>1;
		Pushdown(no,r-l+1);
		if(en<=mid)		return query(lson,st,en);
		else if(st>mid)	return query(rson,st,en);
		else
		{
			ll llen=(st<=l?r-l+1-((r-l+1)>>1):mid-st+1),
				rlen=(en>=r?(r-l+1)>>1:en-mid);
			par lp=query(lson,st,en),rp=query(rson,st,en),ret;
			ret.first.first=lp.first.first+lp.second.first*rlen+rp.first.first+rp.second.second*llen;
			ret.first.second=lp.first.second+rp.first.second;
			ret.second.first=lp.second.first+rp.second.first+rp.first.second*llen;
			ret.second.second=lp.second.second+rp.second.second+lp.first.second*rlen;
			return ret;
		}
	}
}
int main()
{
	ll n,m,i,j,k,l,r;
	ll v,u,d,g;
	scanf("%lld%lld",&n,&m);
	n--;
	for(i=1;i<=m;i++)
	{
		scanf("%s",&str);
		if(str[0]=='C')
		{
			scanf("%lld%lld%lld",&l,&r,&v);
			update(1,n,1,l,r-1,v);
		}
		else
		{
			scanf("%lld%lld",&l,&r);
			u=query(1,n,1,l,r-1).first.first;
			d=(r-l+1)*(r-l)/2;
			g=gcd(u,d);
			printf("%lld/%lld\n",u/g,d/g);
		}
	}
	return 0;
}
时间: 2024-10-10 16:27:57

bzoj-2752 高速公路 road的相关文章

Bzoj 2752 高速公路 (期望,线段树)

Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时候把\(r - 1\)就好了. 这里的期望显然就是路径的平均值. 期望值: \[\dfrac{\sum_{i=l}^r\sum_{j=l}^{r}dis[i][j]}{C_{r-l+1}^2}\] 下面部分可以直接算出: 上面这一部分比较难维护. 考虑每一条边会被走过多少次. \[ans = \su

【BZOJ 2752】 [HAOI2012]高速公路(road)

2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec Memory Limit: 128 MB Submit: 791 Solved: 282 [Submit][Status][Discuss] Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站. Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1

bzoj 2752 9.20考试第三题 高速公路(road)题解

2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1545  Solved: 593[Submit][Status][Discuss] Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1

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

2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1219  Solved: 446[Submit][Status][Discuss] Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1

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

[HAOI2012]高速公路(road) Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用.高速路刚建成时所有的路段都是免费的.政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价.无聊的

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

2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 608  Solved: 199[Submit][Status] Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站. Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行

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

[BZOJ2752][HAOI2012]高速公路(road) Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用.高速路刚建成时所有的路段都是免费的.政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政

bzoj 2752: [HAOI2012]高速公路(road)

Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用.高速路刚建成时所有的路段都是免费的.政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价.无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开

●BZOJ 2752 [HAOI2012]高速公路(road)

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2752题解: 期望,线段树. 把每个路段看成一个点,那么对于l~R的操作,就可以转化为对l~r(r=R-1)的路段的操作. 对于每个询问,我们只需要依次考虑每个路段出现在多少个区间里面. 令cnt[i]表示i号路段在cnt[i]个区间包含. 即答案为$$\frac{\sum_{i=l}^{r}v[i]*cnt[i]}{(r-l+1)*(r-l+2)/2(区间总数)}$$ 那么就需要在线维护一

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

题意:链接 方法:线段树 解析: 这道题刚开始脑抽想了个O(n/2*(logn)*m)的脑抽算法就写上交了=-= 然而当时我神奇地在草纸上写了个O(sqrt(n)/2*(logn)*m).. 当时在想另一个什么分块的什么东西就没过大脑=-= 然后开始找规律呗. 不妨把权值安到点上. 之后考虑一个点的贡献是什么. 其左边有多少个点,右边有多少个点的乘积. 这很显然啊,就是在枚举大长线段的左右端点啊.. 所以假设某个点的权值是val 那么就是val[i](i-x+1)(y-i+1)对吧. 之后就是展