BZOJ2752[HAOI2012] 高速公路(road)

原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2752

高速公路(road)

Description

Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站。

Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用。高速路刚建成时所有的路段都是免费的。

政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价。

无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开车在这条高速路上行驶时想到了这样一个问题:对于给定的l,r(l

Input

第一行2个正整数N,M,表示有N个收费站,M次调整或询问。

接下来M行,每行将出现以下两种形式中的一种。

C l r v 表示将第l个收费站到第r个收费站之间的所有道路的通行费全部增加v

Q l r 表示对于给定的l,r,要求回答小A的问题

所有C与Q操作中保证1<=l

Output

对于每次询问操作回答一行,输出一个既约分数

若答案为整数a,输出a/1

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

在任何时刻任意道路的费用均为不超过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

题解

先是题意一直没读懂,手动模拟一直都没过样例的 83 8 3 ,最后发现修改操作其实是左闭右开的。。。(-1Day)

码完代码又特么一直爆 long long l o n g   l o n g ,调了半天线段树发现是预处理的时候爆了。。。(-1Day)

这么道垃圾题居然耗了我两天,真的日狗。。。

事实证明,不要老想着去用数据结构维护些骚东西,先老老实实推式子。

先把读进来的 r=1 r − = 1 ,左闭右开真的坑。容易发现,对于 [l,r] [ l , r ] 中的每个收费站,我们可以单独统计贡献,计算有几个区间覆盖了它:

i=lr(il+1)(ri+1)vi=i=1rvi(iri2lr+ill+r+1)=(r+1)(1l)i=1rvi+(l+r)i=1rivii=1ri2vi ∑ i = l r ( i − l + 1 ) ( r − i + 1 ) v i = ∑ i = 1 r v i ( i r − i 2 − l r + i l − l + r + 1 ) = ( r + 1 ) ( 1 − l ) ∑ i = 1 r v i + ( l + r ) ∑ i = 1 r i v i − ∑ i = 1 r i 2 v i

因为 vi v i 前面的系数都是确定值,可以预处理出来,就能方便的统计区间加对维护信息的影响(具体可以看代码),所以三个东西都是可以直接维护的。

最后除的时候记得分母是 (rl+22) ( r − l + 2 2 )

代码
#include<bits/stdc++.h>
#define ll long long
#define ls v<<1
#define rs ls|1
using namespace std;
const int M=4e5+5;
struct sd{ll ans,ansi,ansii;};
sd operator +(sd a,sd b){return (sd){a.ans+b.ans,a.ansi+b.ansi,a.ansii+b.ansii};}
ll sum[M],tag[M],sumi[M],sumii[M],prei[M],preii[M],n,m;
char ch[2];
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void up(int v){sum[v]=sum[ls]+sum[rs],sumi[v]=sumi[ls]+sumi[rs],sumii[v]=sumii[ls]+sumii[rs];}
void push(int v,int le,int ri)
{
    int mid=le+ri>>1;
    tag[ls]+=tag[v],tag[rs]+=tag[v];
    sum[ls]+=tag[v]*(mid-le+1),sum[rs]+=tag[v]*(ri-mid);
    sumi[ls]+=tag[v]*(prei[mid]-prei[le-1]),sumi[rs]+=tag[v]*(prei[ri]-prei[mid]);
    sumii[ls]+=tag[v]*(preii[mid]-preii[le-1]),sumii[rs]+=tag[v]*(preii[ri]-preii[mid]);
    tag[v]=0;
}
void add(int v,int le,int ri,int lb,int rb,int d)
{
    if(lb<=le&&ri<=rb)
    {tag[v]+=d,sum[v]+=1ll*(ri-le+1)*d,sumi[v]+=(prei[ri]-prei[le-1])*d,sumii[v]+=(preii[ri]-preii[le-1])*d;return;}
    int mid=le+ri>>1;push(v,le,ri);
    if(lb<=mid)add(ls,le,mid,lb,rb,d);
    if(mid<rb)add(rs,mid+1,ri,lb,rb,d);
    up(v);
}
sd ask(int v,int le,int ri,int lb,int rb)
{
    if(lb<=le&&ri<=rb)return (sd){sum[v],sumi[v],sumii[v]};
    int mid=le+ri>>1;sd ans;push(v,le,ri);
    ans.ans=ans.ansi=ans.ansii=0;
    if(lb<=mid)ans=ask(ls,le,mid,lb,rb);
    if(mid<rb)ans=ans+ask(rs,mid+1,ri,lb,rb);
    up(v);return ans;
}
void in(){scanf("%d%d",&n,&m);}
void ac()
{
    int l,r,v;sd p;ll ans,g,x;
    for(int i=1;i<=n;++i)prei[i]=prei[i-1]+i,preii[i]=preii[i-1]+1ll*i*i;
    for(int i=1;i<=m;++i)
    {
        scanf("%s%d%d",ch,&l,&r);r-=1;
        if(ch[0]=='C'){scanf("%d",&v);add(1,1,n,l,r,v);}
        else p=ask(1,1,n,l,r),x=1ll*(r-l+2)*(r-l+1)/2,ans=1ll*(l+r)*p.ansi-p.ansii+1ll*(r+1)*(1-l)*p.ans,g=gcd(ans,x),
        printf("%lld/%lld\n",ans/g,x/g);
    }
}
int main(){in();ac();}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值