首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【HDU】5700 - 区间交(线段树 & 贪心)

【HDU】5700 - 区间交(线段树 & 贪心)

作者头像
FishWang
发布2025-08-27 10:25:52
发布2025-08-27 10:25:52
8100
代码可运行
举报
运行总次数:0
代码可运行

点击打开题目

区间交

Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 811 Accepted Submission(s): 364

Problem Description

小A有一个含有 个非负整数的数列与 个区间。每个区间可以表示为 。 它想选择其中 个区间, 使得这些区间的交的那些位置所对应的数的和最大。 例如样例中,选择 与 两个区间就可以啦。

Input

多组测试数据 第一行三个数 。 接下来一行 个数 ,表示lyk的数列 。 接下来 行,每行两个数 ,表示每个区间 。

Output

一行表示答案

Sample Input

代码语言:javascript
代码运行次数:0
运行
复制
   5 2 3
1 2 3 4 6
4 5
2 5
1 4

Sample Output

代码语言:javascript
代码运行次数:0
运行
复制
   10

Source

2016"百度之星" - 初赛(Astar Round2B)

在上一篇博客分析过了,传送门:点击打开链接

代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
#define MAX 100000
#define L o<<1
#define R o<<1|1
LL sum[MAX+5];
struct node
{
	int st,endd;
}a[MAX+5];
struct Tree
{
	int l,r;
	int cover;
}tree[MAX<<2];
bool cmp(node a,node b)
{
	return a.st < b.st;
}
void PushUp(int o)
{
	tree[o].cover = tree[L].cover + tree[R].cover;
}
void Build(int o,int l,int r)
{
	tree[o].l = l;
	tree[o].r = r;
	if (l == r)
	{
		tree[o].cover = 0;		//覆盖点全部初始化为0 
		return;
	}
	int mid = (l + r) >> 1;
	Build(L , l , mid);
	Build(R , mid + 1 , r);
	PushUp(o);
}
void UpDate(int o,int x)		//x位置cover值加一 
{
	if (tree[o].l == tree[o].r)
	{
		tree[o].cover++;
		return;
	}
	int mid = (tree[o].l + tree[o].r) >> 1;
	if (mid >= x)
		UpDate(L , x);
	else
		UpDate(R , x);
	PushUp(o);
}
int Query(int o,int x)		//满足条件的最靠右的端点下标 
{
	if (tree[o].l == tree[o].r)
		return tree[o].l;
	if (tree[R].cover >= x)		//优先从右树中找满足条件的
		return Query(R , x);
	else
		return Query(L , x-tree[R].cover);		//右边不够剩下的点从左树找 
}
int main()
{
	int n,k,m;
	int t;
	while (~scanf ("%d %d %d",&n,&k,&m))
	{
		sum[0] = 0;
		for (int i = 1 ; i <= n ; i++)
		{
			scanf ("%d",&t);
			sum[i] = sum[i-1] + t;
		}
		for (int i = 1 ; i <= m ; i++)
			scanf ("%d %d",&a[i].st,&a[i].endd);
		sort (a+1 , a+1+m , cmp);		//对左端点排序 
		Build(1,1,n);
		for (int i = 1 ; i <= k ; i++)		//前k-1个数的左端点不用枚举,直接更新其右端点即可 
			UpDate(1,a[i].endd);
		LL ans = 0;
		a[m+1].endd = 1;		//随便赋值一个,防止最后一次循环出问题 
		for (int i = k ; i <= m ; i++)		//从第k个点开始
		{
			int pos = Query(1,k);
			if (pos >= a[i].st)
				ans = max (ans , sum[pos] - sum[a[i].st-1]);
			UpDate(1,a[i+1].endd);		//将下一点的右端点加入,即其cover值加一 
		}
		printf ("%lld\n",ans);
	}
	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 区间交
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档