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