IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Ezzat and Grid(dp/线段树) -> 正文阅读

[数据结构与算法]Ezzat and Grid(dp/线段树)

题目
题意:给定一个 n ? 1 0 9 n*10^9 n?109的点阵,现在给出m个线段,线段 i , l , r i,l,r i,l,r表示第 i i i行区间 [ l , r ] [l,r] [l,r]取1。现在最少需要删去多少行,才能使得剩下的行中,任何相邻的两行,都至少有一个共同的列,取值都为1。
官方题解
思路:思考最多能保留多少行。 d p [ i ] [ j ] dp[i][j] dp[i][j]表示从第1行到第i行,对于列j来说,能保留的最多行数。则有
d p [ i ] [ j ] = 1 + m a x ( d p [ i ? 1 ] [ k ] ) , k ∈ C i , i f g r i d [ i ] [ j ] = 1 dp[i][j] = 1 + max(dp[i-1][k]), k \in C_i, if grid[i][j]=1 dp[i][j]=1+max(dp[i?1][k]),kCi?,ifgrid[i][j]=1
d p [ i ] [ j ] = d p [ i ? 1 ] [ j ] , i f g r i d [ i ] [ j ] ≠ 1 dp[i][j] = dp[i-1][j], if grid[i][j]\neq1 dp[i][j]=dp[i?1][j],ifgrid[i][j]?=1
维护区间的最大值,可以用线段树。由于列范围比较大,需要进行下标压缩。
由于答案要求输出具体删除的行,我们可以用pre数组保存dp状态。详见参考代码。
细节比较多,考察的点也多。太懒了没打代码(其实是太菜了)
代码

#define  _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define ONLINE_JUDGE
#define endl "\n"
#define ll long long
#define sz(s) (int)(s.size())
#define INF 0x3f3f3f3f3f3f3f3fLL
#define all(v) v.begin(),v.end()
#define watch(x) cout<<(#x)<<" = "<<x<<endl
const int dr[]{ -1, -1, 0, 1, 1, 1, 0, -1 };
const int dc[]{ 0, 1, 1, 1, 0, -1, -1, -1 };
#if __cplusplus >= 201402L
template<typename T>
vector<T> create(size_t n) {
	return vector<T>(n);
}
template<typename T, typename ... Args>
auto create(size_t n, Args ... args) {
	return vector<decltype(create<T>(args...))>(n, create<T>(args...));
}
#endif
void run() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
#else
#endif
}


const pair<int, int> NIL = { 0,-1 };
struct segment_tree {
#define LEFT (idx<<1)
#define RIGHT (idx<<1|1)
#define MID (start+end>>1)
	int n;
	vector<pair<int, int>> tree, lazy;
	segment_tree(int n) :n(n) {
		tree = lazy = vector<pair<int, int>>(n << 2, NIL);
	}
	void push_down(int idx, int start, int end) {
		if (lazy[idx] == NIL)
			return;
		tree[idx] = max(tree[idx], lazy[idx]);
		if (start != end) {
			lazy[LEFT] = max(lazy[LEFT], lazy[idx]);
			lazy[RIGHT] = max(lazy[RIGHT], lazy[idx]);
		}
		lazy[idx] = NIL;
	}
	void update(int idx, int start, int end, int l, int r, pair<int, int> p) {
		push_down(idx, start, end);
		if (r < start || end < l)
			return;
		if (l <= start && end <= r) {
			lazy[idx] = max(lazy[idx], p);
			push_down(idx, start, end);
			return;
		}
		update(LEFT, start, MID, l, r, p);
		update(RIGHT, MID + 1, end, l, r, p);
		tree[idx] = max(tree[LEFT], tree[RIGHT]);
	}
	pair<int, int> query(int idx, int start, int end, int l, int r) {
		push_down(idx, start, end);
		if (r < start || end < l)
			return NIL;
		if (l <= start && end <= r)
			return tree[idx];
		return max(query(LEFT, start, MID, l, r),
			query(RIGHT, MID + 1, end, l, r));
	}
	void update(int l, int r,pair<int,int> p) {
		update(1, 1, n, l, r, p);
	}
	pair<int, int> query(int l, int r) {
		return query(1, 1, n, l, r);
	}
};
int main() {
	run();
	int n, m;
	cin >> n >> m;
	vector<vector<pair<int, int>>> v(n);
	vector<int> id;
	while (m--) {
		int i, l, r;
		cin >> i >> l >> r;
		id.push_back(l);
		id.push_back(r);
		v[i - 1].push_back({ l,r });
	}
	sort(all(id));
	id.erase(unique(all(id)), id.end());
	for (int i = 0; i < n; i++)
		for (auto& it : v[i]) {
			// 取upper_bound,确保从1开始 
			it.first = upper_bound(all(id), it.first) - id.begin();
			it.second = upper_bound(all(id), it.second) - id.begin();
		}
	segment_tree seg(id.size());
	vector<int> prv(n, -1);
	for (int i = 0; i < n; i++) {
		pair<int, int> mx = NIL;
		for (auto& it : v[i])
			mx = max(mx, seg.query(it.first, it.second));

		prv[i] = mx.second;
		mx.first++;
		mx.second = i;
		for (auto& it : v[i])
			seg.update(it.first, it.second, mx);
	}
	pair<int, int> p = seg.query(1, id.size());
	vector<bool> vis(n);
	int cur = p.second;
	while (cur != -1) {
		vis[cur] = true;
		cur = prv[cur];
	}

	cout << n - p.first << endl;
	for (int i = 0; i < n; i++)
		if (!vis[i])
			cout << i + 1 << ' ';
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 12:18:53  更:2021-08-19 12:19:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:52:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码