首页 > 其他分享 >P1668 USACO04DEC Cleaning Shifts S 题解

P1668 USACO04DEC Cleaning Shifts S 题解

时间:2024-10-24 11:02:54浏览次数:1  
标签:const int 题解 线段 USACO04DEC maxt Shifts 优化 DP

P1668 USACO04DEC Cleaning Shifts S - 洛谷

分析

这道题最快的做法应该是贪心,但是线段树优化 DP 也可以做。

首先看到此题,可以想到一个很暴力的区间 DP:\(f[i][j]\) 表示在 \([i, j]\) 时段内最少需要的奶牛数量。对于每头牛的空闲时段 \([l, r]\),其每个子区间答案均为 \(1\);对于其他的部分,像[[P1880 NOI1995 石子合并]] 一样转移就行了。时间效率 \(O(t^3)\),可以拿 \(35\) 分。

优化一下,把区间 DP 优化为线性 DP,令 \(f[i]\) 表示覆盖时段 \([1, i]\) 所需要的最少奶牛数量。首先显然覆盖一个区间至少需要一头奶牛。如果一头奶牛的覆盖区间为 \([l, r]\),其中 \(l = 1\),那么 \(f[r] = 1\),这是 \(f[r]\) 的最优解。而对于 \(l \not= 1\) 的情况,则可以和前面的状态合并:\(f[r] = \min_{l - 1 \le i < r}\{f[i] + 1\}\)。为保证转移的顺序,应该先按照右端点排序。现在时间效率 \(O(nt)\),仍然不够。

继续优化,注意到上面的方程需要找到 \([l - 1, r)\) 的最小状态。Look familiar? 我们考虑使用线段树优化,用一棵维护最小值的线段树来存状态。再来想想这棵线段树需要哪些功能:根据上面的方程可知需要区间查询,然后针对每个状态的更新,只需要单点修改即可。由于引入了线段树,时间效率优化为了 \(O(n \log t)\),可通过本题。

代码

暴力区间 DP

#include <bits/stdc++.h>  
using namespace std;  
  
const int maxn = 25005;  
const int maxt = 8005;  
int n, t;  
int f[maxt][maxt];  
  
int main() {  
    scanf("%d%d", &n, &t);  
    memset(f, 0x3f, sizeof(f));  
    for (int i = 1; i <= n; i++) {  
        int l, r;  
        scanf("%d%d", &l, &r);  
        for (int j = l; j <= r; j++) {  
            for (int k = j; k <= r; k++) {  
                f[j][k] = 1;  
            }  
        }  
    }  
    for (int len = 1; len <= t; len++) {  
        for (int i = 1, j; (j = i + len - 1) <= t; i++) {  
            for (int k = i; k < j; k++) {  
                f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j]);  
            }  
        }  
    }  
    printf("%d", f[1][t] == 0x3f3f3f3f ? -1 : f[1][t]);  
    return 0;  
}

未优化的线性 DP

#include <bits/stdc++.h>
using namespace std;

const int maxn = 2.5e4 + 5;
const int maxt = 1e6 + 5;
int n, t;
int f[maxt];
struct Node {
	int l, r;
	bool operator < (const Node &rhs) const {
		return r < rhs.r;
	}
} node[maxn];

int main() {
	scanf("%d%d", &n, &t);
	memset(f, 0x3f, sizeof(f));
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &node[i].l, &node[i].r);
		if (node[i].l == 1) f[node[i].r] = 1;
	}
	sort(node + 1, node + 1 + n);
	for (int i = 1; i <= n; i++) {
		for (int j = node[i].l - 1; j < node[i].r; j++) {
			f[node[i].r] = min(f[node[i].r], f[j] + 1);
		}
	}
	printf("%d", f[t] == 0x3f3f3f3f ? -1 : f[t]);
	return 0;
}

线段树优化 DP

#include <bits/stdc++.h>
using namespace std;

const int maxn = 2.5e4 + 5;
const int maxt = 1e6 + 5;
int n, t;
struct SegmentTree {
	int left, right;
	int minv;
} tree[maxt << 2];
struct Node {
	int l, r;
	bool operator < (const Node &rhs) const {
		return r < rhs.r;
	}
} node[maxn];

inline void pushup(int root) {
	tree[root].minv = min(tree[root << 1].minv, tree[root << 1 | 1].minv);
}

void build(int root, int l, int r) {
	tree[root].left = l;
	tree[root].right = r;
	if (l == r) {
		tree[root].minv = 0x3f3f3f3f;
		return;
	}
	int mid = (l + r) >> 1;
	build(root << 1, l, mid);
	build(root << 1 | 1, mid + 1, r);
	pushup(root);
}

void update(int root, int pos, int val) {
	if (tree[root].left == tree[root].right) {
		tree[root].minv = val;
		return;
	}
	int mid = (tree[root].left + tree[root].right) >> 1;
	if (mid >= pos) update(root << 1, pos, val);
	else update(root << 1 | 1, pos, val);
	pushup(root);
}

int query(int root, int l, int r) {
	if (tree[root].left >= l && tree[root].right <= r) {
		return tree[root].minv;
	}
	int mid = (tree[root].left + tree[root].right) >> 1;
	int ans = 0x3f3f3f3f;
	if (mid >= l) ans = min(ans, query(root << 1, l, r));
	if (mid < r) ans = min(ans, query(root << 1 | 1, l, r));
	return ans;
}

int main() {
	scanf("%d%d", &n, &t);
	build(1, 1, t);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &node[i].l, &node[i].r);
		if (node[i].l == 1) update(1, node[i].r, 1);
	}
	sort(node + 1, node + 1 + n);
	for (int i = 1; i <= n; i++) {
		update(1, node[i].r, min(query(1, node[i].r, node[i].r), query(1, node[i].l - 1, node[i].r - 1) + 1));
	}
	printf("%d", query(1, t, t) == 0x3f3f3f3f ? -1 : query(1, t, t));
	return 0;
}

标签:const,int,题解,线段,USACO04DEC,maxt,Shifts,优化,DP
From: https://www.cnblogs.com/jxyanglinus/p/18499180

相关文章

  • AtCoder Snuke21 J. Drink Bar 部分分题解
    这里将每一个三元组\((a_i,b_i,c_i)\)称为一组数。Subtask1暴力枚举所有的非空子集即可。枚举方式可以采用类似状压DP的二进制枚举或者直接DFS。时间复杂度\(O(N\times2^N)\)。Subtask2性质:此时的特征值最多由两个有效组组成,原因可见Subtask3。因为\(a_i=......
  • P7074 [CSP-J2020] 方格取数 题解
    动态规划dp方格取数类似于数字三角形,均可以使用动态规划直接秒杀.但此题有$3$个方向:上、右、下.所以可以定义一个三维数组dp数组.假设$f_{i,j,1}$是从右、上方到达$(i,j)$的和的最大值.又有$f_{i,j,0}$是从右、下方到达$(i,j)$的和的最大值.我们可以先确定......
  • P7912 [CSP-J 2021] 小熊的果篮 题解
    是模拟吗?其实是的,虽然$1\len\le2\times10^5$,但是队列是个好东西.我们定义一个结构体,来存放每一个块的信息,包括类型、起点、终点,将它们放入队列当中,再使用基于广搜的思想,先处理,再合并,所以需要用到$2$个队列.注意点数据中可能会有块的类型全是$1$,或者全是$0$的情况......
  • P7071 [CSP-J2020] 优秀的拆分 题解
    二进制"优秀的拆分"如果存在,则代表$n$的二进制最低位不是$1$.$\because2^0=1$$\therefore$当$n$的二进制最低位为$1$时,不存在优秀的拆分.即$n$不是奇数.上述条件判断完后,就可以从$2$的$30$次方开始模拟(int的上限是$2^{31}-1$).代码#include<iostream>......
  • P7072 [CSP-J2020] 直播获奖 题解
    暴力使用$\Theta(n^2)$的时间复杂度来解决这题大约能拿到$60pts$.即枚举$p$,再枚举每个选手的分数.正解桶是个好东西.我们开一个桶,记录当前分数有多少人.然后计算获奖人数,分数从大到小进行枚举,直到当前人数$\ge$获奖人数.代码#include<iostream>#include<cstdio>#i......
  • [CSP-J2020] 表达式 题解
    短路这道题目中所含的运算符只有3个:与、或、非.在与运算和或运算中有2个性质.进行与运算时,若其中有一个值为0,则这个运算的结果就为0,即无需判断另1个数是否是0或1.进行或运算时,若其中有一个值为1,则这个运算的结果就为1,也无需判断另一个数是否是0或1.表达式树根据短路的性......
  • 题解 SS241023D【数颜色】/ ZROI3029【静态邻域数颜色】
    静态邻域数颜色-题目-ZhengruiOnlineJudge题目描述静态树上邻域数颜色。给一棵\(n\)个点的无根树,第\(i\)个点颜色为\(a_i\)。有\(q\)次询问,每次询问如下:给定\(x,d\),考虑所有距离\(x\)不超过\(d\)的点,求有多少种不同的颜色。形式化地,给定\(x,d\),求\(|\{a......
  • 题解 P5326【[ZJOI2019] 开关】/ SS241023B【判断题】
    已经沦落为可以随便搬进模拟赛的模板题了。。。题目描述当前有\(n\)道判断题,初始全选的错。初始给出每道题的正确答案,设\(0\)表示错,\(1\)表示对。每道题有一个参数\(p_i\),每轮会以\(\frac{p_i}{\sum_{j=1}^{n}p_j}\)的概率选择第\(i\)道题并修改(flip)这道题的答......
  • [COCI2009-2010#4] PALACINKE 题解
    前言题目链接:洛谷。题意简述\(n\)个点,\(m\)条边。每条边上有商店,经过一条边花费\(1\)单位时间,如果在边上的商店购物,额外花费\(1\)单位时间。需要购买\(4\)种物品,每个商店售出\(1\sim4\)种物品不等。请问,在\(T\)个单位时间内,从\(1\)出发购物,得到这\(4\)种物品......
  • [算法题解] Codeforces round 979 --D. QED's Favorite Permutation
    题目链接:https://codeforces.com/contest/2030/problem/D题目:题解:FavotitePermutation即每个数满足i=p[i];此题中,p数组每次询问后保持不变,s根据询问而改变。因此每次需要进行交换的数的位置是相同的,只需要检验s变更后,操作能否满足交换需求与否。故创建需数组need,预处理nee......