1. 程式人生 > >●BZOJ 2752 [HAOI2012]高速公路(road)

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

brush int sca font char esp get cpp true

題鏈:

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(區間總數)}$$
那麽就需要在線維護一些,使得能夠快速求出上面的值。
考慮每個路段的貢獻:
i號路段被(i-l+1)*(r-i+1)個區間包含,


所以貢獻為:(i-l+1)*(r-i+1)*v[i],把其展開:
=(l+r)*i*v[i]-l*r*v[i]-l*v[i]+r*v[i]-i*i*v[i]+v[i]。
所以,我們只需要用線段樹維護每個區間的路段的v[i]的和,i*v[i]的和,i*i*v[i]的和;


代碼:

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
long long sumi[MAXN],sumi2[MAXN];
struct SGT{
	int size,root;
	int ls[MAXN*2],rs[MAXN*2],lazy[MAXN*2];
	long long sumval[MAXN*2],sumival[MAXN*2],sumi2val[MAXN*2];
	void Pushup(int u){
		sumval[u]=sumval[ls[u]]+sumval[rs[u]];
		sumival[u]=sumival[ls[u]]+sumival[rs[u]];
		sumi2val[u]=sumi2val[ls[u]]+sumi2val[rs[u]];
	}
	void Add(int &u,int l,int r,int v){
		if(!u) u=++size;
		sumval[u]+=1ll*(r-l+1)*v;
		sumival[u]+=(sumi[r]-sumi[l-1])*v;
		sumi2val[u]+=(sumi2[r]-sumi2[l-1])*v;
		lazy[u]+=v;
	}
	void Pushdown(int u,int l,int mid,int r){
		Add(ls[u],l,mid,lazy[u]);
		Add(rs[u],mid+1,r,lazy[u]);
		lazy[u]=0;
	}
	void Modify(int &u,int l,int r,int al,int ar,int v){
		if(!u) u=++size;
		if(al<=l&&r<=ar) return Add(u,l,r,v);
		int mid=(l+r)>>1;
		if(lazy[u]) Pushdown(u,l,mid,r);
		if(al<=mid) Modify(ls[u],l,mid,al,ar,v);
		if(mid<ar) Modify(rs[u],mid+1,r,al,ar,v);
		Pushup(u);
	}
	long long Contribution(int u,int al,int ar){
		return sumival[u]*(al+ar)-sumval[u]*al*ar-sumval[u]*al+sumval[u]*ar-sumi2val[u]+sumval[u];
//		return sumival[u]*(al+ar)-sumval[u]*al*ar+sumval[u]*ar-sumival[u]-sumi2val[u];
	}
	long long Query(int u,int l,int r,int al,int ar){
		if(!u) return 0;
		if(al<=l&&r<=ar) return Contribution(u,al,ar);
		int mid=(l+r)>>1; long long ret=0;
		if(lazy[u]) Pushdown(u,l,mid,r);
		if(al<=mid) ret+=Query(ls[u],l,mid,al,ar);
		if(mid<ar) ret+=Query(rs[u],mid+1,r,al,ar);
		return ret;
	}
}DT;
int N,M;
long long gcd(long long a,long long b){
	while(b^=a^=b^=a%=b);
	return a;
}
int main(){
	char ch; int l,r,v;
	scanf("%d%d",&N,&M);
	for(int i=1;i<=N;i++)
		sumi[i]=sumi[i-1]+i,sumi2[i]=sumi2[i-1]+1ll*i*i;
	for(int i=1;i<=M;i++){
		scanf(" %c %d %d",&ch,&l,&r); r--;
		if(ch==‘C‘) scanf("%d",&v),DT.Modify(DT.root,1,N,l,r,v);
		else {
			long long a=DT.Query(DT.root,1,N,l,r);
			long long b=1ll*(r-l+1)*(r-l+2)/2;
			long long g=gcd(a,b);
			a/=g; b/=g; printf("%lld/%lld\n",a,b);
		}
	}
	return 0;
}

  

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