URAL 1855 Trade Guilds of Erathia

题意:有N个城市,M个操作。城市形成一条链,下标分别从1到N,相邻城市有一条道路相连,初始通过每条道路的费用为0。有两种类型的操作,(1)"change a b d",表示从城市a到城市b之间的每条道路的费用改变d(如果d大于0,增加,反之减少)。(2)"establish a b",表示查询在城市a到城市b之间任意选两个城市作为道路的起点和终点,问通过这些道路的平均费用。

        设当前的道路起点是在K,终点是在K+1,那么这条路径在区间[L,R]之间加的次数是可以知道的,所以这条道路在这次查询中贡献的费用为seg[k]*[(K-L+1)*(R-K)],(K-L+1)*(R-K)展开可以化简为:-K^2 + K(R-L-1) - R(L-1),即a*K^2+b*K+c。而对于每个查询,K的值都是不变的,变的只是系数a、b、c。我们用三棵线段树分别去维护区间内seg[K]*K^2,seg[K]*K,seg[K]的和,乘以每次询问对应的系数,就知道总费用,除以次数,就是答案了。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))

typedef long long LL;
const int N=1e5+5;

LL base[N][3];
struct Segtree
{
	LL mult[N*4],sum[N*4],delay[N*4];
	void fun(int ind,LL valu)
	{
		sum[ind]+=valu*mult[ind]; delay[ind]+=valu;
	}
	void PushUp(int ind)
	{
		sum[ind]=sum[LL(ind)]+sum[RR(ind)];
	}
	void PushDown(int ind)
	{
		if(delay[ind])
		{
			fun(LL(ind),delay[ind]);
			fun(RR(ind),delay[ind]);
			delay[ind]=0;
		}
	}
	void build(int lft,int rht,int ind,int type)
	{
		mult[ind]=sum[ind]=delay[ind]=0;

		if(lft==rht) mult[ind]=base[lft][type];
		else
		{
			int mid=MID(lft,rht);
			build(lft,mid,LL(ind),type);
			build(mid+1,rht,RR(ind),type);

			mult[ind]=mult[LL(ind)]+mult[RR(ind)];
		}
	}
	void updata(int st,int ed,int dx,int lft,int rht,int ind)
	{
		if(st<=lft&&rht<=ed)
		{
			fun(ind,dx);
		}
		else
		{
			PushDown(ind);
			int mid=MID(lft,rht);
			if(st<=mid) updata(st,ed,dx,lft,mid,LL(ind));
			if(ed> mid) updata(st,ed,dx,mid+1,rht,RR(ind));
			PushUp(ind);
		}
	}
	LL query(int st,int ed,int lft,int rht,int ind)
	{
		if(st<=lft&&rht<=ed) return sum[ind];
		else
		{
			PushDown(ind);
			int mid=MID(lft,rht);
			LL sum1=0,sum2=0;
			if(st<=mid) sum1=query(st,ed,lft,mid,LL(ind));
			if(ed> mid) sum2=query(st,ed,mid+1,rht,RR(ind));
			PushUp(ind);
			return sum1+sum2;
		}
	}
}seg[3];
int main()
{
	//freopen("E.in","r",stdin);

	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(int i=1;i<=n;i++)
		{
			base[i][0]=1;
			base[i][1]=(LL)i;
			base[i][2]=(LL)i*(LL)i;
		}
		n--;
		for(int i=0;i<3;i++) seg[i].build(1,n,1,i);

		char buf[50];
		int st,ed,valu;
		while(m--)
		{
			scanf("%s",buf);
			if(buf[0]=='c')
			{
				scanf("%d%d%d",&st,&ed,&valu);
				for(int i=0;i<3;i++) seg[i].updata(st,ed-1,valu,1,n,1);
			}
			else
			{
				scanf("%d%d",&st,&ed);
				LL a=-seg[2].query(st,ed-1,1,n,1);
				LL b=seg[1].query(st,ed-1,1,n,1);
				LL c=seg[0].query(st,ed-1,1,n,1);

				//cout<<"a="<<a<<" b="<<b<<" c="<<c<<endl;

				LL tmp=ed-st+1;
				double ans=a+b*(st+ed-1)+c*ed*(1-st);
				ans*=2;
				ans/=(tmp);
				ans/=(tmp-1);
				printf("%.10lf\n",ans);
			}
		}
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/shiqi_614/article/details/9940103