D1. Too Many Segments (easy version)

区间线段删除优化:差分法求最小删除次数
本文介绍了一种解决区间线段重合问题的方法,通过使用差分数组计算每个点的线段覆盖数,找出需要删除的线段以满足限制条件,最终输出最小删除次数和对应的线段编号。

题目:样例1:

输入
7 2
11 11
9 11
7 8
8 9
7 8
9 11
7 9

输出
3
1 4 7 

样例2:

输入
5 1
29 30
30 30
29 29
28 30
30 30

输出
3
1 2 4 

样例3:

输入
6 1
2 3
3 3
2 3
2 2
2 3
2 3

输出
4
1 3 5 6 

思路:

                这里数据范围是 200,所以我们完全可以暴力遍历每一个点是否在该区间内,这里需要注意的是,可以通过差分的方式达到区间总和的变化,所以要学会掌握好差分。

代码详解如下:

#include <iostream>
#include <unordered_map>
#define endl '\n'
#define YES puts("YES")
#define NO puts("NO")
#define umap unordered_map
#pragma GCC optimize(3,"Ofast","inline")
#define ___G std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e6 + 10;

struct Range
{
	int l,r;
}a[N];

int n,m;
umap<int,int>b;
umap<int,bool>r;
inline void solve()
{
	cin >> n >> m;
	for(int i = 1;i <= n;++i)
	{
		int l,r;
		cin >> l >> r;
		
		// 差分数组
		++b[l];
		--b[r + 1];
			
		a[i] = {l,r};
	}	
	
	// 差分前缀和,构造出每一个点所在位置的当前点前缀总和
	for(int i = 1;i <= 200;++i) b[i] += b[i - 1];
	
	int sz = 0;		// 删除线段数量
	
	// 开始遍历每一个点
	for(int i = 1;i <= 200;++i)
	{
		// 如果当前线段所在的点有超过了规定可重合部分 m
		// 则开始选择删除
		while(b[i] > m)
		{
			int tem = 0;	// tem 作为探头,探索哪一个需要删除的
			// 开始遍历每一个线段,寻找合适删除的线段
			for(int j = 1;j <= n;++j)
			{
				// 如果当前线段范围更广,那么应该删除,tem = j
				if(a[j].l <= i && a[j].r >= i && (!tem || a[j].r > a[tem].r) && !r[j]) tem = j;
			}
			
			// 标记已选择删除的线段
			r[tem] = true;
			
			// 累加删除线段
			++sz;
			
			// 更新区间所在点的覆盖线段数量
			for(int j = a[tem].l;j <= a[tem].r;++j) --b[j];
		}
	}
	
	// 输出答案,删除的线段
	cout << sz << endl;
	for(int i = 1;i <= 200;++i)
	{
		if(r[i]) cout << i << ' ';
	}
}


int main()
{
//	freopen("a.txt", "r", stdin);
	___G;
	int _t = 1;
//	cin >> _t;
	while (_t--)
	{
		solve();
	}

	return 0;
}

最后提交:

### 问题分析 在 Apache Doris 中,`too many segments in rowset` 是一个与写入机制和数据组织结构相关的性能问题。Doris 的数据以追加方式写入,并以微批的形式形成 Rowset,每个 Rowset 包含多个 Segment[^1]。当系统频繁写入小批量数据时,可能会导致 Rowset 中的 Segment 数量过多,从而影响读取性能和元数据管理效率。 ### 解决方案 #### 1. **调整写入频率与微批大小** 由于每次导入操作都会生成一个新的 Rowset[^2],频繁的小批量写入会迅速增加 Rowset 和 Segment 的数量。为缓解该问题,可以采用“攒微批+降频率”的策略,即适当延长写入间隔,积累更多数据后再进行一次写入操作。这样可以减少 Rowset 的生成频率,降低 Segment 增长速度。 #### 2. **优化 Compaction 策略** Rowset 经过 Compaction 后会合并多个版本,形成更大的 Rowset 并减少 Segment 总数。因此,提升 Compaction 的效率可以有效缓解 Segment 过多的问题。可以通过以下方式优化: - 调整 `tablet_max_versions` 参数,限制 Tablet 的最大版本数。 - 配置更激进的 Compaction 策略(如增大 `cumulative_compaction_num_threads` 和 `base_compaction_num_threads`)以加速合并过程。 #### 3. **调整 Segment 文件大小阈值** Doris 在写入过程中根据配置决定是否新建 Segment 文件。如果单个 Segment 文件较小,则容易产生大量文件。可通过调整如下参数控制 Segment 大小: ```properties # 设置每个Segment的最大行数 max_rows_per_segment = 1048576 # 设置每个Segment的最大数据大小(字节数) max_segment_file_size = 1073741824 # 1GB ``` 适当提高上述参数值可减少 Segment 的创建频率。 #### 4. **监控与诊断** 利用 Doris 提供的系统表和日志信息对 Rowset 及 Segment 的增长情况进行监控。例如查询 `information_schema` 中的 `TABLET_SEGMENTS` 表来查看各 Tablet 的 Segment 分布情况,及时发现异常增长点并进行干预。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值