【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 }

时间: 2024-10-07 18:47:31

【BZOJ2752】【线段树】高速公路的相关文章

【BZOJ2752】[HAOI2012]高速公路(road) 线段树

[BZOJ2752][HAOI2012]高速公路(road) Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用.高速路刚建成时所有的路段都是免费的.政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政

BZOJ 2752: [HAOI2012]高速公路(road) [线段树 期望]

2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1219  Solved: 446[Submit][Status][Discuss] Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1

BZOJ 2752:[HAOI2012]高速公路(road)(线段树)

[HAOI2012]高速公路(road) Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用.高速路刚建成时所有的路段都是免费的.政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价.无聊的

Bzoj 2752 高速公路 (期望,线段树)

Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时候把\(r - 1\)就好了. 这里的期望显然就是路径的平均值. 期望值: \[\dfrac{\sum_{i=l}^r\sum_{j=l}^{r}dis[i][j]}{C_{r-l+1}^2}\] 下面部分可以直接算出: 上面这一部分比较难维护. 考虑每一条边会被走过多少次. \[ans = \su

BZOJ 2752 [HAOI2012]高速公路(road) 线段树

题意:链接 方法:线段树 解析: 这道题刚开始脑抽想了个O(n/2*(logn)*m)的脑抽算法就写上交了=-= 然而当时我神奇地在草纸上写了个O(sqrt(n)/2*(logn)*m).. 当时在想另一个什么分块的什么东西就没过大脑=-= 然后开始找规律呗. 不妨把权值安到点上. 之后考虑一个点的贡献是什么. 其左边有多少个点,右边有多少个点的乘积. 这很显然啊,就是在枚举大长线段的左右端点啊.. 所以假设某个点的权值是val 那么就是val[i](i-x+1)(y-i+1)对吧. 之后就是展

JZYZOJ1527 [haoi2012]高速公路 线段树 期望

http://172.20.6.3/Problem_Show.asp?id=1527 日常线段树的pushdown写挂,果然每次写都想得不全面,以后要注意啊--求期望部分也不熟练,和平均数搞混也是orz,我已经是个期望都求不出来的废人了.这道题显然(大概)每个段的贡献是val[i]*(y-i+1)*(i-x+1);整体来说算是一看就是线段树的题. 代码 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring>

【Luogu】P2221高速公路(线段树乱搞)

题目链接 这题……我从一开始就想歪了qwq. 为了缅怀逝去的一小时我就把我的30分暴力思路放上来. 首先我们观察枚举的区间.假设我们要枚举的范围是1~5之间的四条路,为了方便我们把它们叫做abcd. 那么观察我们枚举的区间. a ab abc abcd b bc bcd c cd d 观察有一些区间是可以合起来的. 然后观察a出现4次,b出现6次,c出现6次,d出现4次. 是有一定规律的qwq 然后就$\frac{nm}{2}的复杂度搞搞 就三十分 正确思路是,观察一条路选不选上(设这条路左点x

【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路的两端都是城市(可能两端是同一个城市),保证任意两个城市都可以通过高速公路互达. 国正在筹划“八纵八横”的高铁建设计划,计划要修建一些高速铁路,每条高速铁路两端也都是城市(可能两端是同一个城市),也都有一个非负整数的经济影响因子.国家还计划在“八纵八横”计划建成之后,将“一带一路”扩展为“一带_路一

线段树进阶

T1:高速公路 题干: $Y901$ 高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站. $Y901$ 高速公路是一条由 $N-1$ 段路以及 $N$ 个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1-N,从收费站 i 行驶到 i+1 (或从 i+1 行驶到 i )需要收取 V_i 的费用.高速路刚建成时所有的路段都是免费的. 政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或

[poj2104]可持久化线段树入门题(主席树)

解题关键:离线求区间第k小,主席树的经典裸题: 对主席树的理解:主席树维护的是一段序列中某个数字出现的次数,所以需要预先离散化,最好使用vector的erase和unique函数,很方便:如果求整段序列的第k小,我们会想到离散化二分和线段树的做法, 而主席树只是保存了序列的前缀和,排序之后,对序列的前缀分别做线段树,具有差分的性质,因此可以求任意区间的第k小,如果主席树维护索引,只需要求出某个数字在主席树中的位置,即为sort之后v中的索引:若要求第k大,建树时反向排序即可 1 #include