【BZOJ2752】【线段树】高速公路
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
Source
【分析】
比较简单的题目,推一下就知道要维护的值。
但是细节比较多,并且要维护好几个值,容易写错,建议在草稿纸上对着公式打。
明明超内存被bzoj说成TLE,你让我情何以堪...
1 /* 2 宋代志南 3 《绝句》 4 古木阴中系短篷,杖藜扶我过桥东。 5 沾衣欲湿杏花雨,吹面不寒杨柳风。 6 */ 7 #include <iostream> 8 #include <cstdio> 9 #include <algorithm> 10 #include <cstring> 11 #include <vector> 12 #include <utility> 13 #include <iomanip> 14 #include <string> 15 #include <cmath> 16 #include <queue> 17 #include <assert.h> 18 #include <map> 19 #include <ctime> 20 #include <cstdlib> 21 #include <stack> 22 #define LOCAL 23 const int MAXN = 500000 + 10; 24 const int MAXM = 1000000 + 10; 25 const int INF = 100000000; 26 const int SIZE = 450; 27 const int maxnode = 1000000 + 10; 28 using namespace std; 29 long long add(long long val, long long len){ 30 return val * (((len * (len + 1)) / 2) * len + (len * (len + 1)) / 2 - (len * (len + 1) * (2 * len + 1)) / 6); 31 } 32 long long n, m; 33 struct SEGTREE{ 34 struct Node{ 35 long long l, r; 36 long long sum, sum2, sum3;//代表总段和和带权和后面是反向的 37 long long addn, val;//val值代表整个区间的值 38 Node *ch[2]; 39 bool delta;//标记 40 41 void pushdown(){//标记下传 42 if (l == r) return; 43 if (delta){ 44 ch[0]->addn += addn; 45 ch[1]->addn += addn; 46 ch[0]->delta = 1;ch[0]->sum += add(addn, ch[0]->r - ch[0]->l + 1);ch[0]->val += addn * (ch[0]->r - ch[0]->l + 1); 47 ch[1]->delta = 1;ch[1]->sum += add(addn, ch[1]->r - ch[1]->l + 1);ch[1]->val += addn * (ch[1]->r - ch[1]->l + 1); 48 long long len = ch[0]->r - ch[0]->l + 1; 49 ch[0]->sum2 += addn * ((len * (len + 1)) / 2); 50 ch[0]->sum3 += addn * ((len * (len + 1)) / 2); 51 len = ch[1]->r - ch[1]->l + 1; 52 ch[1]->sum2 += addn * ((len * (len + 1)) / 2); 53 ch[1]->sum3 += addn * ((len * (len + 1)) / 2); 54 delta = 0; 55 addn = 0; 56 } 57 return; 58 } 59 void update(){ 60 if (l == r) return; 61 val = ch[0]->val + ch[1]->val; 62 //正反向 63 sum2 = ch[0]->sum2 + ch[1]->sum2 + ch[1]->val * (ch[0]->r - ch[0]->l + 1); 64 sum3 = ch[1]->sum3 + ch[0]->sum3 + ch[0]->val * (ch[1]->r - ch[1]->l + 1); 65 sum = 0; 66 sum += ch[0]->sum + ch[0]->sum2 * (ch[1]->r - ch[1]->l + 1); 67 sum += ch[1]->sum + ch[1]->sum3 * (ch[0]->r - ch[0]->l + 1); 68 return; 69 } 70 }*root, mem[maxnode]; 71 long long tot; 72 73 void init(){ 74 root = NULL; 75 tot = 0; 76 build(root, 1, n - 1);//n个点n-1条边 77 } 78 Node *NEW(long long l, long long r){ 79 Node *p = &mem[tot++]; 80 p->l = l; 81 p->r = r; 82 p->addn = p->delta = p->val = p->sum2 = 0; 83 return p; 84 } 85 void build(Node *&t, long long l, long long r){ 86 if (t == NULL){ 87 t = NEW(l, r); 88 } 89 if (l == r) return; 90 long long mid = (l + r) >> 1; 91 build(t->ch[0], l, mid); 92 build(t->ch[1], mid + 1, r); 93 return; 94 } 95 //lr一段的值全部加val 96 void insert(Node *&t, long long l, long long r, long long val){ 97 t->pushdown(); 98 if (l <= t->l && t->r <= r){ 99 t->delta = 1; 100 t->addn += val; 101 t->sum += add(val, t->r - t->l + 1); 102 t->val += val * (t->r - t->l + 1); 103 long long len = t->r - t->l + 1; 104 t->sum2 += val * ((len * (len + 1)) / 2); 105 t->sum3 += val * ((len * (len + 1)) / 2); 106 return; 107 } 108 long long mid = (t->l + t->r) >> 1; 109 if (l <= mid) insert(t->ch[0], l, r, val); 110 if (r > mid) insert(t->ch[1], l, r, val); 111 t->update(); 112 } 113 long long query(Node *&t, long long l, long long r){ 114 t->pushdown(); 115 if (l <= t->l && t->r <= r){ 116 long long Ans = t->sum; 117 //先朝右边扩张 118 Ans += (t->sum2 * (r - t->r)); 119 Ans += ((t->sum3 + t->val * (r - t->r)) * (t->l - l)); 120 return Ans; 121 } 122 long long mid = (t->l + t->r) >> 1; 123 long long tmp = 0; 124 if (l <= mid) tmp += query(t->ch[0], l, r); 125 if (r > mid) tmp += query(t->ch[1], l, r); 126 t->update(); 127 return tmp; 128 } 129 }A; 130 131 void init(){ 132 scanf("%lld%lld", &n, &m); 133 A.init(); 134 } 135 long long gcd(long long a, long long b){return b == 0 ? a: gcd(b, a % b);} 136 void work(){ 137 for (long long i = 1; i <= m; i++){ 138 char str[5]; 139 scanf("%s", str); 140 if (str[0] == 'C'){ 141 long long l, r; 142 long long val; 143 scanf("%lld%lld%lld", &l, &r, &val); 144 r--; 145 A.insert(A.root, l, r, val); 146 }else if (str[0] == 'Q'){ 147 long long l, r; 148 scanf("%lld%lld", &l, &r); 149 long long tmp = r - l + 1; 150 r--; 151 if (l == 1 && r == 3) 152 printf(""); 153 long long a = A.query(A.root, l, r), b = (tmp * (tmp - 1)) / 2; 154 long long c = gcd(a, b); 155 printf("%lld/%lld\n", a / c, b / c); 156 } 157 } 158 } 159 160 int main(){ 161 162 init(); 163 work(); 164 return 0; 165 }