[HAOI2012]高速公路(BZOJ2752)
题目在这儿:http://www.lydsy.com/JudgeOnline/problem.php?id=2752
2752: [HAOI2012]高速公路(road)
Description
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将期望花费多少费用呢?
Input
第一行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
Output
对于每次询问操作回答一行,输出一个既约分数
若答案为整数a,输出a/1
Sample Input
C 1 4 2
C 1 2 -1
Q 1 2
Q 2 4
Q 1 4
Sample Output
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
题目比较裸,维护的东西比较恶心,具体展开应该是∑A[i]*(r-i+1)(i-l+1),展开后维护三个sum值即可,注意一定要强类型转换T_T...
Codes:
1 #include<cmath> 2 #include<queue> 3 #include<vector> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 using namespace std; 10 const int N = 100010; 11 typedef long long lld; 12 #define Ch1 (i<<1) 13 #define Ch2 (Ch1|1) 14 #define For(i,n) for(int i=1;i<=n;i++) 15 #define Rep(i,l,r) for(int i=l;i<=r;i++) 16 17 struct SUM{ 18 lld a,b,c; 19 SUM(){ 20 a = b = c = 0; 21 } 22 }; 23 24 struct tnode{ 25 int l,r,mid; 26 SUM sum; 27 lld mark; 28 }T[N<<1]; 29 lld iidi[N],idi[N],delta; 30 int n,m,l,r; 31 32 SUM operator + (const SUM &A,const SUM &B){ 33 SUM C; 34 C.a = A.a + B.a; 35 C.b = A.b + B.b; 36 C.c = A.c + B.c; 37 return C; 38 } 39 40 void Pushdown(int i){ 41 if(T[i].mark&&T[i].l!=T[i].r){ 42 T[Ch1].mark+=T[i].mark; T[Ch2].mark += T[i].mark; 43 T[Ch1].sum.a += T[i].mark * (iidi[T[Ch1].r]-iidi[T[Ch1].l-1]); 44 T[Ch2].sum.a += T[i].mark * (iidi[T[Ch2].r]-iidi[T[Ch2].l-1]); 45 T[Ch1].sum.b += T[i].mark * (idi[T[Ch1].r]-idi[T[Ch1].l-1]); 46 T[Ch2].sum.b += T[i].mark * (idi[T[Ch2].r]-idi[T[Ch2].l-1]); 47 T[Ch1].sum.c += T[i].mark * lld(T[Ch1].r-T[Ch1].l+1); 48 T[Ch2].sum.c += T[i].mark * lld(T[Ch2].r-T[Ch2].l+1); 49 T[i].mark = 0; 50 } 51 } 52 53 void Build(int l,int r,int i){ 54 T[i].l = l; T[i].r = r; T[i].mid = (l+r)/2; 55 if(l==r) return; 56 Build(l,T[i].mid,Ch1);Build(T[i].mid+1,r,Ch2); 57 } 58 59 void Modify(int l,int r,lld delta,int i){ 60 if(l>r) return; 61 if(T[i].l==l&&T[i].r==r){ 62 T[i].sum.a+=delta*(iidi[r]-iidi[l-1]); 63 T[i].sum.b+=delta*(idi[r]-idi[l-1]); 64 T[i].sum.c+=delta*lld(r-l+1); 65 T[i].mark+=delta; 66 return; 67 } 68 Pushdown(i); 69 Modify(l,min(T[i].mid,r),delta,Ch1);Modify(max(l,T[i].mid+1),r,delta,Ch2); 70 T[i].sum = T[Ch1].sum + T[Ch2].sum; 71 } 72 73 SUM Query(int l,int r,int i){ 74 if(T[i].l==l&&T[i].r==r) return T[i].sum; 75 Pushdown(i); 76 if(r<=T[i].mid) return Query(l,r,Ch1); else 77 if(l>T[i].mid) return Query(l,r,Ch2); else 78 return Query(l,T[i].mid,Ch1) + Query(T[i].mid+1,r,Ch2); 79 } 80 81 lld gcd(lld a,lld b){ 82 return (b)?gcd(b,a%b):(a); 83 } 84 85 void Out(SUM Ans,lld M){ 86 lld ans = -Ans.a + lld(r+l) * Ans.b - lld(r+1) * lld(l-1) * Ans.c; 87 lld gcds = gcd(ans,M); 88 printf("%lld/%lld\n",ans/gcds,M/gcds); 89 } 90 91 void init(){ 92 scanf("%d%d",&n,&m); 93 Build(1,n,1); 94 For(i,n){ 95 iidi[i] = iidi[i-1]+ lld(i) * lld(i); 96 idi[i] = idi[i-1] + i; 97 } 98 } 99 100 int main(){ 101 init();char op; 102 For(i,m){ 103 scanf("\n"); 104 scanf("%c ",&op); 105 if(op=='C') {scanf("%d%d%lld",&l,&r,&delta);r--;Modify(l,r,delta,1);} 106 else {scanf("%d%d",&l,&r);r--;Out(Query(l,r,1),lld(r-l+2)*lld(r-l+1)/lld(2));} 107 } 108 return 0; 109 }