Description
Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站。
Y901高速公路是一条由
N−1
段路以及
N
个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为
政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价。
无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开车在这条高速路上行驶时想到了这样一个问题:对于给定的
l,r(l<r)
,在第
l
个到第
Input
第一行
2
个正整数
接下来
M
行,每行将出现以下两种形式中的一种:
C
Q
所有C与Q操作中保证
1<=l<r<=N
。
Output
对于每次询问操作回答一行,输出一个既约分数。
若答案为整数
a
,输出
Sample Input
4 5
C 1 4 2
C 1 2 -1
Q 1 2
Q 2 4
Q 1 4
Sample Output
1/1
8/3
17/6
HINT
数据规模
所有C操作中的
v
的绝对值不超过
在任何时刻任意道路的费用均为不超过
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 |
Source
思路
纯数学题啊……考虑一条道路
i
对答案的贡献(记为
代码
#include <cstdio>
const int maxn=100000;
struct data
{
long long v,vi,vii;
data operator +=(const data &other)
{
v+=other.v;
vi+=other.vi;
vii+=other.vii;
return *this;
}
data(long long vv=0,long long vvi=0,long long vvii=0):v(vv),vi(vvi),vii(vvii){}
};
struct segment_tree
{
long long v[(maxn<<2)+10],vi[(maxn<<2)+10],vii[(maxn<<2)+10],lazy[(maxn<<2)+10];
long long updata(long long now)
{
v[now]=v[now<<1]+v[now<<1|1];
vi[now]=vi[now<<1]+vi[now<<1|1];
vii[now]=vii[now<<1]+vii[now<<1|1];
return 0;
}
long long push(long long now,long long left,long long right,long long q)
{
v[now]+=q*(right-left+1);
vi[now]+=(q*(left+right)*(right-left+1))>>1;
vii[now]+=q*(right*(right+1)*((right<<1)+1)-(left-1)*left*((left<<1)-1))/6;
lazy[now]+=q;
return 0;
}
long long pushdown(long long now,long long left,long long right)
{
if(lazy[now])
{
long long mid=(left+right)>>1;
push(now<<1,left,mid,lazy[now]);
push(now<<1|1,mid+1,right,lazy[now]);
lazy[now]=0;
}
return 0;
}
long long build(long long now,long long left,long long right)
{
if(left==right)
{
lazy[now]=v[now]=vi[now]=vii[now]=0;
return 0;
}
lazy[now]=v[now]=vi[now]=vii[now]=0;
long long mid=(left+right)>>1;
build(now<<1,left,mid);
build(now<<1|1,mid+1,right);
return 0;
}
long long add(long long now,long long left,long long right,long long askl,long long askr,long long cval)
{
if((askl<=left)&&(right<=askr))
{
push(now,left,right,cval);
return 0;
}
long long mid=(left+right)>>1;
pushdown(now,left,right);
if(askl<=mid)
{
add(now<<1,left,mid,askl,askr,cval);
}
if(mid<askr)
{
add(now<<1|1,mid+1,right,askl,askr,cval);
}
updata(now);
return 0;
}
data query(long long now,long long left,long long right,long long askl,long long askr)
{
if((askl<=left)&&(right<=askr))
{
return data(v[now],vi[now],vii[now]);
}
pushdown(now,left,right);
long long mid=(left+right)>>1;
data res=data();
if(askl<=mid)
{
res+=query(now<<1,left,mid,askl,askr);
}
if(mid<askr)
{
res+=query(now<<1|1,mid+1,right,askl,askr);
}
return res;
}
};
long long n,m,a,b,c;
char s[10];
segment_tree st;
data ans;
long long gcd(long long a,long long b)
{
if(!b)
{
return a;
}
else
{
return gcd(b,a%b);
}
}
int main()
{
scanf("%lld%lld",&n,&m);
--n;
st.build(1,1,n);
while(m--)
{
scanf("%s%I64d%I64d",s,&a,&b);
if(s[0]=='C')
{
scanf("%lld",&c);
st.add(1,1,n,a,b-1,c);
}
else
{
ans=st.query(1,1,n,a,b-1);
long long t=ans.v*(-a*b+b)+ans.vi*(a+b-1)-ans.vii;
if(!t)
{
puts("0/1");
}
else
{
long long m=((b-a)*(b-a+1))>>1,g=gcd(t,m);
printf("%lld/%lld\n",t/g,m/g);
}
}
}
return 0;
}