洛谷 P2221 [HAOI2012] 高速公路

来源:互联网 发布:同比环比数据分析 编辑:程序博客网 时间:2024/05/18 09:09

题目描述

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

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

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

无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开车在这条高速路上行驶时想到了这样一个问题:对于给定的l,r(l < r),在第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操作中保证1<=l < r<=N

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

若答案为整数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


【分析】
用线段树维护三个值
sum
id[l]*key[l]+…+id[r]*keyr
id[l]^2*key[l]+…+id[r]^2*keyr
然后列个式子就可以推出答案了…
以前想用splay维护这个东西,结果没有搞出来qwq,前前后后废了两个多小时qwq


【代码】

#include<iostream>#include<cstring>#include<cstdio>#define ll long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=200005;int n,m;struct tree {int l,r,id;ll mark,sum,sum_1,sum_2;} t[mxn<<2]; inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();    return x*f;}inline void update(int num){    t[num].sum=t[num<<1].sum+t[num<<1|1].sum;    t[num].sum_1=t[num<<1].sum_1+t[num<<1|1].sum_1;    t[num].sum_2=t[num<<1].sum_2+t[num<<1|1].sum_2;}inline void ope(int num,ll c){    ll l=t[num].l,r=t[num].r;    t[num].mark+=c;    t[num].sum+=(ll)(r-l+1)*c;    t[num].sum_1+=(l+r)*(r-l+1)*c/2;    t[num].sum_2+=c*(r*(r+1)*(r+r+1)/6-l*(l-1)*(l+l-1)/6);}inline void pushdown(int num){    if(t[num].mark)    {        if(t[num].l==t[num].r) return;        ope(num<<1,t[num].mark),ope(num<<1|1,t[num].mark);        t[num].mark=0;    }}inline void build(int num,int l,int r){    t[num].l=l,t[num].r=r;    if(l==r) return;    int mid=l+r>>1;    build(num<<1,l,mid);    build(num<<1|1,mid+1,r);    update(num);}inline void add(int num,int L,int R,int c){    if(L<=t[num].l && t[num].r<=R)    {        ope(num,c);return;    }    pushdown(num);    if(L<=t[num<<1].r) add(num<<1,L,R,c);    if(R>=t[num<<1|1].l) add(num<<1|1,L,R,c);    update(num);}inline ll query0(int num,int L,int R){    ll ans=0;    if(L<=t[num].l && t[num].r<=R)      return t[num].sum;    pushdown(num);    if(L<=t[num<<1].r) ans+=query0(num<<1,L,R);    if(R>=t[num<<1|1].l) ans+=query0(num<<1|1,L,R);    return ans;}inline ll query1(int num,int L,int R){    ll ans=0;    if(L<=t[num].l && t[num].r<=R)      return t[num].sum_1;    pushdown(num);    if(L<=t[num<<1].r) ans+=query1(num<<1,L,R);    if(R>=t[num<<1|1].l) ans+=query1(num<<1|1,L,R);    return ans;}inline ll query2(int num,int L,int R){    ll ans=0;    if(L<=t[num].l && t[num].r<=R)      return t[num].sum_2;    pushdown(num);    if(L<=t[num<<1].r) ans+=query2(num<<1,L,R);    if(R>=t[num<<1|1].l) ans+=query2(num<<1|1,L,R);    return ans;}inline ll gcd(ll x,ll y){    if(x<y) swap(x,y);    return x%y==0?y:gcd(y,x%y);}int main(){//  freopen("roadxw.in","r",stdin);//  freopen("roadxw.out","w",stdout);    int i,j,w,x,y;    char s[3];    n=read(),m=read();    build(1,1,n-1);     while(m--)    {        scanf("%s",s);        if(s[0]=='C')        {            x=read(),y=read(),w=read();            add(1,x,y-1,w);        }        else        {            x=read(),y=read();            ll zero=query0(1,x,y-1),one=query1(1,x,y-1),two=query2(1,x,y-1);//          printf("test=%lld %lld %lld\n",zero,one,two);            ll ans=(ll)zero*y*(1-x)+(ll)one*(x+y-1)-two,mu=(ll)(y-x+1)*(ll)(y-x)/2;            if(ans==0)            {                printf("0/1\n");                continue;            }            ll yue=gcd(ans,mu);            ans/=yue,mu/=yue;            printf("%lld/%lld\n",ans,mu);        }    }    return 0;}/*4 5C 1 4 2C 1 2 -1Q 1 2Q 2 4Q 1 4*/
0 0