洛谷P4198 楼房重建

题意:给定序列,每次修改一个值,求前缀最大值的个数。

解:线段树经典应用。

每个节点维护最大值和该区间前缀最大值个数。

发现我们不用下传标记,只需要合并区间。

需要实现一个函数int ask([l r] lm)求出区间[l r]中前一个数是lm时前缀最大值个数。

那么当lm >= large[ls]时,return ask([mid r] lm)

这个很好理解,左子区间的所有数都不会成为前缀最大值。

当lm < large[ls]时,return ask([l mid] lm) + (sum[o] - sum[ls])

这个注意,不是sum[rs]因为sum[rs]的意义是从0开始,而这个的前面会有large[ls]挡着,所以是sum[o] - sum[ls]

修改的时候先一路到底把large值改了。然后return的时候把沿途区间都更新。

具体来说就是sum[o] = ask([l r] 0)...等等,好像有问题。

lm < large[ls]的时候,求值是要调用sum[o]的,这不就循环调用导致出错了吗?

所以写成sum[o] = sum[ls] + ask([mid r] large[ls])即可。

本题不用建树。需要建树的时候就跟修改类似的写法即可。

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 const int N = 100010;
 5 
 6 double a[N], large[N << 2];
 7 int n, sum[N << 2];
 8 
 9 int ask(int l, int r, int o, double lm) {
10     if(l == r) {
11         return (lm < a[r]);
12     }
13     int mid = (l + r) >> 1;
14     if(lm > large[o << 1]) {
15         return ask(mid + 1, r, o << 1 | 1, lm);
16     }
17     else {
18         return sum[o] - sum[o << 1] + ask(l, mid, o << 1, lm);
19     }
20 }
21 
22 void change(int p, double v, int l, int r, int o) {
23     if(l == r) {
24         large[o] = v;
25         sum[o] = 1;
26         return;
27     }
28     int mid = (l + r) >> 1;
29     if(p <= mid) {
30         change(p, v, l, mid, o << 1);
31     }
32     else {
33         change(p, v, mid + 1, r, o << 1 | 1);
34     }
35     large[o] = std::max(large[o << 1], large[o << 1 | 1]);
36     sum[o] = sum[o << 1] + ask(mid + 1, r, o << 1 | 1, large[o << 1]);
37     return;
38 }
39 
40 int main() {
41     int m;
42     scanf("%d%d", &n, &m);
43     for(int i = 1, x, y; i <= m; i++) {
44         scanf("%d%d", &x, &y);
45         a[x] = (double)(y) / x;
46         change(x, a[x], 1, n, 1);
47         printf("%d\n", sum[1]);
48     }
49 
50     return 0;
51 }
AC代码

 

转载于:https://www.cnblogs.com/huyufeifei/p/10325023.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的楼房销售系统的 Python 代码: ```python class House: def __init__(self, address, price, area, rooms): self.address = address self.price = price self.area = area self.rooms = rooms class Salesman: def __init__(self, name, commission): self.name = name self.commission = commission def sell_house(self, house, buyer): if buyer.budget >= house.price: buyer.budget -= house.price self.commission += house.price * 0.1 print("Congratulations, " + buyer.name + "! You have successfully purchased " + house.address + " for " + str(house.price) + " dollars.") else: print("Sorry, " + buyer.name + "! You cannot afford " + house.address + ".") class Buyer: def __init__(self, name, budget): self.name = name self.budget = budget salesman = Salesman("John", 0) house1 = House("123 Main St", 500000, 2000, 4) house2 = House("456 Elm St", 300000, 1500, 3) house3 = House("789 Oak St", 700000, 2500, 5) buyer1 = Buyer("Alice", 600000) buyer2 = Buyer("Bob", 400000) salesman.sell_house(house1, buyer1) # Congratulations, Alice! You have successfully purchased 123 Main St for 500000 dollars. salesman.sell_house(house2, buyer2) # Sorry, Bob! You cannot afford 456 Elm St. salesman.sell_house(house3, buyer2) # Congratulations, Bob! You have successfully purchased 789 Oak St for 700000 dollars. ``` 这个系统包含三个类:House、Salesman 和 Buyer。House 类表示一栋房子,包含地址、价格、面积和房间数等属性。Salesman 类表示销售员,包含名字和佣金等属性,以及一个 sell_house 方法,用于销售房子。Buyer 类表示买家,包含名字和预算等属性。在主程序中,创建了三个 House 对象和两个 Buyer 对象,然后调用 Salesman 的 sell_house 方法进行销售。如果买家的预算足够支付房子的价格,销售员会计算佣金并打印一条祝贺消息;否则会打印一条失败消息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值