[BZOJ2752][HAOI2012]高速公路

BZOJ
Luogu

sol

看上去是道数学期望题但实际上是个傻逼数据结构
首先答案的形式应该就是

\[\frac{\mbox{[l,r]区间内的子区间权值之和}}{\mbox{[l,r]区间内的子区间个数}} \]

个数的话就是\((r-l+1)*(r-l)/2\)
总和的话,考虑每一段公路的贡献:

\[ans=\sum_{i=l}^{r-1}(i-l+1)*(r-i)*V_i\\=\sum_{i=l}^{r-1}[-i^2+(l+r-1)*i-lr+r]*V_i\\=\sum_{i=l}^{r-1}-V_ii^2+V_ii(l+r-1)-V_i(lr-r) \]

所以线段树维护一下\(\sum V_i\)\(\sum V_ii\)\(\sum V_ii^2\)即可。为了压一点常数可以预处理出\(\sum i\)\(\sum i^2\)你硬是不想预处理也没有人拦你

code

谁来治一治我这压行。。。(硬是压进了70行呢)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long
const int N = 100005;
int gi()
{
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
ll s[N<<2],si[N<<2],sii[N<<2],len[N<<2],i1[N<<2],i2[N<<2],tag[N<<2],ans1,ans2,ans3,p,q,gg;
int n,m;
void build(int x,int l,int r)
{
	if (l==r) {len[x]=1,i1[x]=l,i2[x]=1ll*l*l;return;}
	int mid=l+r>>1;
	build(x<<1,l,mid);build(x<<1|1,mid+1,r);
	len[x]=len[x<<1]+len[x<<1|1],i1[x]=i1[x<<1]+i1[x<<1|1],i2[x]=i2[x<<1]+i2[x<<1|1];
}
void pushup(int x){s[x]=s[x<<1]+s[x<<1|1],si[x]=si[x<<1]+si[x<<1|1],sii[x]=sii[x<<1]+sii[x<<1|1];}
void cover(int x,int v){s[x]+=len[x]*v,si[x]+=i1[x]*v,sii[x]+=i2[x]*v,tag[x]+=v;}
void pushdown(int x){cover(x<<1,tag[x]);cover(x<<1|1,tag[x]);tag[x]=0;}
void modify(int x,int l,int r,int ql,int qr,int v)
{
	if (l>=ql&&r<=qr) {cover(x,v);return;}
	pushdown(x);int mid=l+r>>1;
	if (ql<=mid) modify(x<<1,l,mid,ql,qr,v);
	if (qr>mid) modify(x<<1|1,mid+1,r,ql,qr,v);
	pushup(x);
}
void query(int x,int l,int r,int ql,int qr)
{
	if (l>=ql&&r<=qr) {ans1+=s[x],ans2+=si[x],ans3+=sii[x];return;}
	pushdown(x);int mid=l+r>>1;
	if (ql<=mid) query(x<<1,l,mid,ql,qr);
	if (qr>mid) query(x<<1|1,mid+1,r,ql,qr);
}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int main()
{
	n=gi();m=gi();
	build(1,1,n-1);
	while (m--)
	{
		char ch=getchar();
		while (ch!='C'&&ch!='Q') ch=getchar();
		if (ch=='C')
		{
			int l=gi(),r=gi(),v=gi();
			modify(1,1,n-1,l,r-1,v);
		}
		else
		{
			int l=gi(),r=gi();
			ans1=ans2=ans3=0;
			query(1,1,n-1,l,r-1);
			p=ans1*(r-1ll*l*r)+ans2*(l+r-1)-ans3;
			q=1ll*(r-l+1)*(r-l)/2;
			gg=gcd(p,q);p/=gg;q/=gg;
			printf("%lld/%lld\n",p,q);
		}
	}
	return 0;
}
posted @ 2018-02-02 10:29  租酥雨  阅读(256)  评论(0编辑  收藏  举报