题目描述
Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站。
Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用。高速路刚建成时所有的路段都是免费的。
政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价。
无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开车在这条高速路上行驶时想到了这样一个问题:对于给定的 ,在第l个到第r个收费站里等概率随机取出两个不同的收费站a和b,那么从a行驶到b将期望花费多少费用呢?
输入输出格式
输入格式:
第一行2个正整数N,M,表示有N个收费站,M次调整或询问
接下来M行,每行将出现以下两种形式中的一种
C l r v 表示将第l个收费站到第r个收费站之间的所有道路的通行费全部增加v
Q l r 表示对于给定的l,r,要求回答小A的问题
所有C与Q操作中保证
输出格式:
对于每次询问操作回答一行,输出一个既约分数
若答案为整数a,输出a/1
输入输出样例
输入样例#1:
4 5
C 1 4 2
C 1 2 -1
Q 1 2
Q 2 4
Q 1 4
输出样例#1:
1/1
8/3
17/6
说明
所有C操作中的v的绝对值不超过10000
在任何时刻任意道路的费用均为不超过10000的非负整数
所有测试点的详细情况如下表所示
Test N M
1 =10 =10
2 =100 =100
3 =1000 =1000
4 =10000 =10000
5 =50000 =50000
6 =60000 =60000
7 =70000 =70000
8 =80000 =80000
9 =90000 =90000
10 =100000 =100000
分析:
两个高速站中间的费用我们可以看做一个数,那么询问
之间的和相当于询问第
到第
个数的和,这样会方便一些。
我们考虑答案可以由总贡献除以事件个数求得,主要就是求总贡献。
我们考虑每一个数的贡献,显然当一个区间跨越了这一个数时,也就是一个端点在左边,另一个端点再右边,这个数便有贡献(我们设的数时两个高速站的费用,所以取 这种区间其实在高速上是不同的两个点,可以存在)。
那么,显然有,
根据分配率化简一下,
整理一下可得,
因为有区间修改,可以用线段树把 , , 维护一下。
其中,选择方案数为 ,平方和公式为 。
由于一开始推错了式子,所以代码中 放到了最后面。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
const int maxn=1e5+7;
using namespace std;
typedef long long LL;
struct node{
LL sum1,sum2,sum3;
LL lazy1,lazy2,lazy3;
}t[maxn*4];
int n,m,l,r;
LL x;
char s[1];
LL getsum_power1(int l,int r)
{
return (LL)(l+r)*1ll*(r-l+1)/2;
}
void add1(int p,int l,int r,int x,int y,LL k)
{
if ((l==x) && (r==y))
{
t[p].lazy1+=k;
t[p].sum1+=getsum_power1(l,r)*k;
return;
}
int mid=(l+r)/2;
if (t[p].lazy1)
{
t[p*2].lazy1+=t[p].lazy1;
t[p*2].sum1+=getsum_power1(l,mid)*t[p].lazy1;
t[p*2+1].lazy1+=t[p].lazy1;
t[p*2+1].sum1+=getsum_power1(mid+1,r)*t[p].lazy1;
t[p].lazy1=0;
}
if (y<=mid) add1(p*2,l,mid,x,y,k);
else
{
if (x>mid) add1(p*2+1,mid+1,r,x,y,k);
else
{
add1(p*2,l,mid,x,mid,k);
add1(p*2+1,mid+1,r,mid+1,y,k);
}
}
t[p].sum1=t[p*2].sum1+t[p*2+1].sum1;
}
LL getsum_power2(int l,int r)
{
return (LL)(r*1ll*(r+1)*1ll*(2*r+1)-l*1ll*(l-1)*1ll*(2*l-1))/6;
}
void add2(int p,int l,int r,int x,int y,LL k)
{
if ((l==x) && (r==y))
{
t[p].lazy2+=k;
t[p].sum2+=getsum_power2(l,r)*k;
return;
}
int mid=(l+r)/2;
if (t[p].lazy2)
{
t[p*2].lazy2+=t[p].lazy2;
t[p*2].sum2+=getsum_power2(l,mid)*t[p].lazy2;
t[p*2+1].lazy2+=t[p].lazy2;
t[p*2+1].sum2+=getsum_power2(mid+1,r)*t[p].lazy2;
t[p].lazy2=0;
}
if (y<=mid) add2(p*2,l,mid,x,y,k);
else
{
if (x>mid) add2(p*2+1,mid+1,r,x,y,k);
else
{
add2(p*2,l,mid,x,mid,k);
add2(p*2+1,mid+1,r,mid+1,y,k);
}
}
t[p].sum2=t[p*2].sum2+t[p*2+1].sum2;
}
LL getsum1(int p,int l,int r,int x,int y)
{
if ((l==x) && (r==y)) return t[p].sum1;
int mid=(l+r)/2;
if (t[p].lazy1)
{
t[p*2].lazy1+=t[p].lazy1;
t[p*2].sum1+=getsum_power1(l,mid)*t[p].lazy1;
t[p*2+1].lazy1+=t[p].lazy1;
t[p*2+1].sum1+=getsum_power1(mid+1,r)*t[p].lazy1;
t[p].lazy1=0;
}
if (y<=mid) return getsum1(p*2,l,mid,x,y);
else
{
if (x>mid) return getsum1(p*2+1,mid+1,r,x,y);
else return getsum1(p*2,l,mid,x,mid)+getsum1(p*2+1,mid+1,r,mid+1,y);
}
}
LL getsum2(int p,int l,int r,int x,int y)
{
if ((l==x) && (r==y)) return t[p].sum2;
int mid=(l+r)/2;
if (t[p].lazy2)
{
t[p*2].lazy2+=t[p].lazy2;
t[p*2].sum2+=getsum_power2(l,mid)*t[p].lazy2;
t[p*2+1].lazy2+=t[p].lazy2;
t[p*2+1].sum2+=getsum_power2(mid+1,r)*t[p].lazy2;
t[p].lazy2=0;
}
if (y<=mid) return getsum2(p*2,l,mid,x,y);
else
{
if (x>mid) return getsum2(p*2+1,mid+1,r,x,y);
else return getsum2(p*2,l,mid,x,mid)+getsum2(p*2+1,mid+1,r,mid+1,y);
}
}
void add3(LL p,LL l,LL r,LL x,LL y,LL k)
{
if ((l==x) && (r==y))
{
t[p].lazy3+=k;
t[p].sum3+=(r-l+1)*k;
return;
}
LL mid=(l+r)/2;
if (t[p].lazy3)
{
t[p*2].lazy3+=t[p].lazy3;
t[p*2+1].lazy3+=t[p].lazy3;
t[p*2].sum3+=(mid-l+1)*1ll*t[p].lazy3;
t[p*2+1].sum3+=(r-mid)*1ll*t[p].lazy3;
t[p].lazy3=0;
}
if (y<=mid) add3(p*2,l,mid,x,y,k);
else if (x>mid) add3(p*2+1,mid+1,r,x,y,k);
else
{
add3(p*2,l,mid,x,mid,k);
add3(p*2+1,mid+1,r,mid+1,y,k);
}
t[p].sum3=t[p*2].sum3+t[p*2+1].sum3;
}
LL getsum3(int p,int l,int r,int x,int y)
{
if ((l==x) && (r==y)) return t[p].sum3;
LL mid=(l+r)/2;
if (t[p].lazy3)
{
t[p*2].lazy3+=t[p].lazy3;
t[p*2+1].lazy3+=t[p].lazy3;
t[p*2].sum3+=(mid-l+1)*1ll*t[p].lazy3;
t[p*2+1].sum3+=(r-mid)*1ll*t[p].lazy3;
t[p].lazy3=0;
}
if (y<=mid) return getsum3(p*2,l,mid,x,y);
else if (x>mid) return getsum3(p*2+1,mid+1,r,x,y);
else return getsum3(p*2,l,mid,x,mid)+getsum3(p*2+1,mid+1,r,mid+1,y);
}
LL gcd(LL x,LL y)
{
LL r=x%y;
while (r)
{
x=y;
y=r;
r=x%y;
}
return y;
}
int main()
{
scanf("%d%d",&n,&m);
n--;
for (int i=1;i<=m;i++)
{
scanf("%s",s);
if (s[0]=='C')
{
scanf("%d%d%lld",&l,&r,&x);
add1(1,1,n,l,r-1,x);
add2(1,1,n,l,r-1,x);
add3(1,1,n,l,r-1,x);
}
else
{
scanf("%d%d",&l,&r);
LL y=(LL)(r-l)*1ll*(r-l+1)/2;
r=r-1;
LL ans=(LL)(r+1)*(1-l)*getsum3(1,1,n,l,r)+(l+r)*1ll*getsum1(1,1,n,l,r)-getsum2(1,1,n,l,r);
LL x=ans;
LL d=gcd(x,y);
x/=d;
y/=d;
printf("%lld/%lld\n",x,y);
}
}
}