前言:前辈讲课时设的状态还是有些繁琐,感觉题解设的状态更简洁。

--------------

题目链接

题目大意:给定$n$条道路和$m$场比赛,每个道路修建需要$c_i$,每场比赛需要使用$[l_i,r_i]$内的道路,收益为$p_i$。问最大收益。$n,m\leq 200000$

先将所有的区间右端点从小到大排序。

设$f[i][j]$表示已经考虑前$i$条道路,最右边没有修的道路是$j$。现在考虑转移。

如果不修第$i$条道路,那么最右边的没有修的道路就变成$i$了。有这样的方程$f[i][i]=max(f[i][i],f[i-1][j]) (0\leq j\leq i-1)$

如果修第$i$条道路,那么以$i$为右端点的比赛都能获得收益。有$f[i][j]=f[i-1][j]+p(0\leq j\leq l_i-1)$。但是不要忘记修路的费用,即$f[i][j]=f[i-1][j]-cost[i](0\leq j\leq i-1)$。

这样的转移是$O(n^2)$的,还不够优秀。注意到只需要维护区间最大值和序列和,我们可以用线段树来维护,只用维护懒标记,区间加和区间最大值这三个操作即可。

至于以右端点进行关键字排序,可以开一个$vector$数组来存左端点和值。

时间复杂度$O(n\log n)$。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
struct Node
{
int first,second;
};
vector<Node> a[];
struct node
{
int lazy,a,max;
}tree[];
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if (ch=='-') f=-;ch=getchar();}
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void pushdown(int index)
{
tree[index*].lazy+=tree[index].lazy;
tree[index*+].lazy+=tree[index].lazy;
tree[index*].max+=tree[index].lazy;
tree[index*+].max+=tree[index].lazy;
tree[index].lazy=;
}
inline void update(int index,int l,int r,int ql,int qr,int x)
{
if (ql<=l&&r<=qr) {tree[index].lazy+=x;tree[index].max+=x;return;}
if (tree[index].lazy) pushdown(index);
int mid=(l+r)/;
if (ql<=mid) update(index*,l,mid,ql,qr,x);
if (qr>mid) update(index*+,mid+,r,ql,qr,x);
tree[index].max=max(tree[index*].max,tree[index*+].max);
}
inline int query(int index,int l,int r,int ql,int qr)
{
if (ql<=l&&r<=qr) return tree[index].max;
if (tree[index].lazy) pushdown(index);
int mid=(l+r)/,res=;
if (ql<=mid) res=max(res,query(index*,l,mid,ql,qr));
if (qr>mid) res=max(res,query(index*+,mid+,r,ql,qr));
return res;
}
signed main()
{
n=read(),m=read();
for (int i=;i<=n;i++) tree[i].a=read();
for (int i=;i<=m;i++)
{
int l=read(),r=read(),x=read();
a[r].push_back((Node){l,x});
}
for (int i=;i<=n;i++)
{
//f[i][i]=max(f[i][i],f[i-1][j])
update(,,n,i,i,query(,,n,,i-));
//f[i][j]=f[i-1][j]+p-cost;
for (int j=;j<a[i].size();j++) update(,,n,,a[i][j].first-,a[i][j].second);
update(,,n,,i-,-tree[i].a);
}
printf("%lld",tree[].max);
return ;
}

最新文章

  1. C#设计模式-责任链模式
  2. 【BZOJ-2179&amp;2194】FFT快速傅里叶&amp;快速傅里叶之二 FFT
  3. Oracle数据库优化的经验总结
  4. 替换jenkins上打包完成的安装包的方法
  5. Innodb行锁源码学习(一)
  6. Java maven安装GDAL
  7. 云计算相关的一些概念Baas、Saas、Iaas、Paas
  8. [转]android开发之字节顺序
  9. C#文件和文件文件夹按时间、名称排序-顺序与倒序
  10. C语言中链表节点的实现,以及如何实现泛型
  11. 解决Hibernate Write operations are not allowed in read-only mode的方法
  12. 如何通过apt-get获得安装包的源码
  13. 批量创建prefab
  14. Oracle EBS-SQL (WIP-15):检查车间任务物料未发数量与现有量对照.sql
  15. Boost::Asio::Error的用法浅析
  16. 定时器(setTimeout)的秘密
  17. spring boot项目编译出来的jar包如何更改端口号
  18. yii学习笔记--快速创建一个项目
  19. 痞子衡嵌入式:常用的数据差错控制技术(2)- 奇偶校验(Parity Check)
  20. Android 开发 将window变暗

热门文章

  1. 【题解】uva1104 chips challenge
  2. day63 django入门(4)
  3. day25 ATM项目(第一天)
  4. 用nodejs实现向文件的固定位置插入内容
  5. python数据处理(四)之数据获取与存储
  6. java 面向对象(三十一):异常(四) 自定义异常类
  7. 机器学习实战基础(十四):sklearn中的数据预处理和特征工程(七)特征选择 之 Filter过滤法(一) 方差过滤
  8. Flask 基础组件(三):路由系统
  9. Python之爬虫(二十六) Scrapy登录知乎
  10. cnn卷积理解