题目

实际上经转换得:

给了 \(n(n \le 5 \times 10^5)\) 条线段,求覆盖 \([1..n]\) 需要的最少条数

分析

设 \(f_i\) 表示覆盖了 \([1..n]\) 时需要的最少的线段数

那么 \(O(n^2)\) 的转移是这样的

#include<cstdio>
#include<iostream>
using namespace std; const int N = 5e5 + 5;
int n , a[N] , f[N]; int main()
{
scanf("%d" , &n);
for(register int i = 1; i <= n; i++) scanf("%d" , a + i) , f[i] = N;
for(register int i = 1; i <= n; i++)
for(register int j = 1; j <= n; j++)
{
int l = max(j - a[j] , 1) , r = min(j + a[j] , n);
if (l <= i && i <= r) f[i] = min(f[i] , f[l - 1] + 1);
}
printf("%d" , f[n]);
}

而我们发现在转移时,\(f_i\) 的要取所有满足条件的线段的 \(f_{l-1}\) 的最小值

而要满足的条件就是 \(l \leq i \leq r\)

于是我们用线段树维护

逆着考虑,维护每个 \(f_i\) 能影响的范围

#include<cstdio>
#include<iostream>
#include<cstring>
#define ls (k << 1)
#define rs (ls | 1)
using namespace std; const int N = 5e5 + 5 , INF = 0x3f3f3f3f;
int n , f[N] , nxt[N] , seg[N * 4] , tag[N * 4];
struct node{
int l , r;
}a[N]; void pushdown(int k)
{
if (tag[k] == INF) return;
seg[ls] = min(seg[ls] , tag[k]) , tag[ls] = min(tag[ls] , tag[k]);
seg[rs] = min(seg[rs] , tag[k]) , tag[rs] = min(tag[rs] , tag[k]);
tag[k] = INF;
} void update(int l , int r , int k , int tl , int tr , int v)
{
if (tl <= l && r <= tr)
{
seg[k] = min(seg[k] , v) , tag[k] = min(tag[k] , v);
return;
}
pushdown(k);
int mid = (l + r) >> 1;
if (tl <= mid) update(l , mid , ls , tl , tr , v);
if (tr > mid) update(mid + 1 , r , rs , tl , tr , v);
seg[k] = min(seg[ls] , seg[rs]);
} int query(int l , int r , int k , int x)
{
if (l == r && l == x) return seg[k];
pushdown(k);
int mid = (l + r) >> 1;
if (x <= mid) return query(l , mid , ls , x);
if (x > mid) return query(mid + 1 , r , rs , x);
} int main()
{
scanf("%d" , &n);
int x;
for(register int i = 1; i <= n; i++)
{
scanf("%d" , &x);
a[i].l = max(i - x , 1) , a[i].r = min(i + x , n);
if (a[nxt[a[i].l - 1]].r < a[i].r) nxt[a[i].l - 1] = i;
}
memset(seg , 0x3f3f3f3f , sizeof seg) , memset(tag , 0x3f3f3f3f , sizeof tag);
if (nxt[0] != 0) update(1 , n , 1 , a[nxt[0]].l , a[nxt[0]].r , 0);
for(register int i = 1; i <= n; i++)
{
f[i] = query(1 , n , 1 , i) + 1;
if (nxt[i] != 0) update(1 , n , 1 , a[nxt[i]].l , a[nxt[i]].r , f[i]);
}
printf("%d" , f[n]);
}

最新文章

  1. Unable to create the selected property page. An error occurred while automatically activating bundle net.sourceforge.pmd
  2. sublime text 2 快捷键
  3. Servlet.init() for servlet springMvc
  4. oracle数据库从入门到精通之三
  5. GY编辑平台产品总结
  6. 我的web框架
  7. magento cache,magento index
  8. Oracle 10g bigfile表空间、smallfile 表空间
  9. 警告: [SetContextPropertiesRule]{Context} Setting property &#39;source&#39; to &#39;org.eclipse.jst.jee.server:20160928&#39; did not find a matching property
  10. 搭建 Android 开发环境,初试HelloWorld (win7) (下) (转)
  11. 一.ubuntu14.04安装、亮度设置、显卡设置等一体化讲解
  12. HTML中Id和Name的区别
  13. Cisco笔试——2014年
  14. 5.0、Android Studio调试你的应用
  15. revit融合
  16. team项目学习01
  17. 信息摘要算法之五:HMAC算法分析与实现
  18. PCLVisualizer可视化类
  19. 什么是SpringCloud
  20. jsp调用java servlet

热门文章

  1. adb版本不同导致一个服务杀死另一个服务
  2. GeoServer 2.15.0 开启跨域设置
  3. Day30.1:Math的常用方法
  4. IOS移动端 -webkit-overflow-scrollin属性造成的问题
  5. Django框架:1、手撸web框架、Django框架简介、安装与使用和小白必会三板斧
  6. python从公众号文章中获取二维码
  7. gin模板语法
  8. 图计算引擎分析——Gemini
  9. [OpenCV实战]34 使用OpenCV进行图像修复
  10. vulnhub靶场之HACKER KID: 1.0.1