【HAOI2012】高速公路

题目描述

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

  1 /*
  2     实际上n个点 只有n-1条路 那就删掉最后一个点 
  3     每次询问 r-1
  4     期望定义自己百度去 
  5     这里期望可以用总和除以总状态数 
  6     总状态数显然可以用组合数 即 C(r-l+1,2);
  7     总和指的是可能的收费总和
  8     对于此题我们要对每个点分别计算贡献的话
  9     每个点的贡献为左边点的数目加1的和乘右面点的数量乘这个点的权值
 10     ∑(l-r) v[i]*(i-l+1)*(r-i+1);
 11     化简一下 维护 v[i],v[i]*i,v[i]*i*i 即可 
 12 */
 13 #include<cstdio>
 14 #include<iostream>
 15 #define MAXN 100010
 16 #define LL long long
 17 
 18 using namespace std;
 19 
 20 struct node {
 21     LL l,r;
 22     LL tag;
 23     LL sum1,sum2,sum3;
 24 };
 25 node t[MAXN<<3];
 26 
 27 LL n,m,x,y,v;
 28 
 29 LL p[MAXN],p2[MAXN],p3[MAXN];
 30 
 31 char opt[5];
 32 
 33 inline void read(LL&x) { 
 34     LL f=1;x=0;char c=getchar(); 
 35     while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();} 
 36     while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-48;c=getchar();} 
 37     x=x*f; 
 38 } 
 39 
 40 void build_tree(LL now,LL l,LL r) {
 41     t[now].l=l;
 42     t[now].r=r;
 43     if(l==r) return;
 44     LL mid=(l+r)>>1;
 45     build_tree(now<<1,l,mid);
 46     build_tree(now<<1|1,mid+1,r);
 47 }
 48 
 49 inline void up(LL now) {
 50     t[now].sum1=t[now<<1].sum1+t[now<<1|1].sum1;
 51     t[now].sum2=t[now<<1].sum2+t[now<<1|1].sum2;
 52     t[now].sum3=t[now<<1].sum3+t[now<<1|1].sum3;
 53 }
 54 
 55 inline void down(LL now) {
 56     if(t[now].tag) {
 57         t[now<<1].sum1+=t[now].tag*(p[t[now<<1].r]-p[t[now<<1].l-1]);
 58         t[now<<1].sum2+=t[now].tag*(p2[t[now<<1].r]-p2[t[now<<1].l-1]);
 59         t[now<<1].sum3+=t[now].tag*(p3[t[now<<1].r]-p3[t[now<<1].l-1]);
 60         t[now<<1].tag+=t[now].tag;
 61         t[now<<1|1].sum1+=t[now].tag*(p[t[now<<1|1].r]-p[t[now<<1|1].l-1]);
 62         t[now<<1|1].sum2+=t[now].tag*(p2[t[now<<1|1].r]-p2[t[now<<1|1].l-1]);
 63         t[now<<1|1].sum3+=t[now].tag*(p3[t[now<<1|1].r]-p3[t[now<<1|1].l-1]);
 64         t[now<<1|1].tag+=t[now].tag;
 65         t[now].tag=0;
 66     }
 67     return;
 68 }
 69 
 70 void modify(LL now,LL l,LL r,LL k) {
 71     if(l<=t[now].l&&r>=t[now].r) {
 72         t[now].tag+=k;
 73         t[now].sum1+=(p[t[now].r]-p[t[now].l-1])*k;  //这里应该是+= 而不是赋值 
 74         t[now].sum2+=(p2[t[now].r]-p2[t[now].l-1])*k;
 75         t[now].sum3+=(p3[t[now].r]-p3[t[now].l-1])*k;
 76         return;
 77     }
 78     down(now);
 79     LL mid=(t[now].l+t[now].r)>>1;
 80     if(l<=mid) modify(now<<1,l,r,k);
 81     if(r>mid) modify(now<<1|1,l,r,k);
 82     up(now);
 83 }
 84 
 85 inline void pre() {
 86     for(LL i=1;i<=100000;i++) {
 87         p[i]=p[i-1]+1;
 88         p2[i]=p2[i-1]+i;
 89         p3[i]=p3[i-1]+i*i;
 90     }
 91     return;
 92 }
 93 
 94 LL query1(LL now,LL l,LL r) {
 95     if(l<=t[now].l&&r>=t[now].r) {
 96         return t[now].sum1;
 97     }
 98     down(now);
 99     LL res=0,mid=(t[now].l+t[now].r)>>1;
100     if(l<=mid) res+=query1(now<<1,l,r);
101     if(r>mid) res+=query1(now<<1|1,l,r);
102     return res;
103 }
104 
105 LL query2(LL now,LL l,LL r) {
106     if(l<=t[now].l&&r>=t[now].r) {
107         return t[now].sum2;
108     }
109     down(now);
110     LL res=0,mid=(t[now].l+t[now].r)>>1;
111     if(l<=mid) res+=query2(now<<1,l,r);
112     if(r>mid) res+=query2(now<<1|1,l,r);
113     return res;
114 }
115 
116 LL query3(LL now,LL l,LL r) {
117     if(l<=t[now].l&&r>=t[now].r) {
118         return t[now].sum3;
119     }
120     down(now);
121     LL res=0,mid=(t[now].l+t[now].r)>>1;
122     if(l<=mid) res+=query3(now<<1,l,r);
123     if(r>mid) res+=query3(now<<1|1,l,r);
124     return res;
125 }
126 
127 LL gcd(LL a,LL b) {
128     if(b==0) return a;
129     else gcd(b,a%b);
130 }
131 
132 int main() {
133     read(n);read(m);
134     pre();
135     build_tree(1,1,n-1);
136     for(LL i=1;i<=m;i++) {
137         scanf("%s",opt);
138         if(opt[0]=='C') {
139             read(x);read(y);read(v);
140             modify(1,x,y-1,v);
141         } 
142         else {
143             read(x);read(y);
144             LL ans1=(y-x*y)*query1(1,x,y-1);
145             LL ans2=(x+y-1)*query2(1,x,y-1);
146             LL ans3=-query3(1,x,y-1);
147             LL ans=ans1+ans2+ans3;
148             LL fm=((y-x+1)*(y-x))>>1;
149             LL p=gcd(ans,fm);
150             printf("%lld/%lld
",ans/p,fm/p);
151         }
152     }
153     return 0;
154 }
题解


作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

 
原文地址:https://www.cnblogs.com/whistle13326/p/7306010.html