【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

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

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 }
View Code

 

posted @ 2015-03-14 16:12  TCtower  阅读(138)  评论(0编辑  收藏  举报