cf#535E1

原题链接
标签:贪心,BF暴力算法,遍历
题目的大概意思是给你一串数列,然后再接下来的几行里头,告诉你数列的几个划分(下标的首和尾),然后可以让你随便选不选区间,然后选了就让下标在这些区间里头的数-1,最后要求使得数列的最大值和最小值之差尽可能的大,输出要求就是最大差,然后用到的区间的数量,然后写出输入时区间的序号。
这一题我刚开始是没有什么思路的,顶多想到一个dfs,但是算了一下,显然不行,想了一会儿还是不行,感觉应该是第一次接触这种题型,所以看了一下题解,题解说区间可以分为四个部分,第一个部分是只包括了最大值,第二个部分是只包括了最小值,第三个部分是既有最大值又有最小值,第四个部分是既没有最大值又没有最小值,这里的最大值和最小值都是指的最终变换完之后的,但是我一开始看完以为是指的一开始的最大值和最小值,想了想题解挺有道理的,毕竟对于这种没什么头绪的问题要学着找点规律进行分类。
然后我其实没有懂后面的题解,就试着去写想着让目前的最大数不变,使用所有的没有包括最大数的区间,这样可能可以行得通,但是还是理所应当的WA了,第一个数据就是一个反例,然后还是没有办法,我就去看别的题解,然后发现他其实是假想某一个数如果是最后的最大值,然后再用我之前想的只不选取含有这个下标的区间,其他的全部选取,看得出来的最大差会是多少,然后取那个可以得到最大差的值为最终的最大值,但是不知道这个假想的某一个是哪个哇,所以就遍历每一个,这也就是用到BF的地方,匹配条件就是可以形成最大差的数字,我们需要找到那个数字,找到之后就好办了,然后就直接写了。
这里需要反思一下和dfs的区别我觉得,dfs是把所有的可能性漫无目的的列出来,然后取最大差的可能,而这里的BF是从另一个角度遍历所有可能的情况,是一个假设某一个条件,那么可以有贪心的算法继续下去,这个假设的条件的并集就刚好是所有的可能,这样的遍历更有方向性。
附上源代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
#include<map>
using namespace std;
FILE *stream;
#define ll long long
#define N 305
#define zwh freopen_s(&stream,"in.txt","r",stdin), freopen_s(&stream,"out.txt","w",stdout);
int a[N],b[N][2],d[N];
int zwh[N];
int n, m, cntd = 1;
int maxs;
int max(int n)
{
	int maxx = zwh[1];
	for (int i = 1; i <= n; i++)
	{
		if (maxx < zwh[i])
			maxx = zwh[i];
	}
	return maxx;
}
int min(int n)
{
	int minn = zwh[1];
	for (int i = 1; i <= n; i++)
	{
		if (minn > zwh[i])
			minn = zwh[i];
	}
	return minn;
}
int f(int maxx)
{
	cntd = 1;
	for (int i = 1; i <= n; i++)
	{
		zwh[i] = a[i];
	}
	for (int i = 1; i <= m; i++)
	{
		if (b[i][0] > maxx || b[i][1] < maxx)
		{
			d[cntd++] = i;
		}
	}
	for (int i = 1; i <= cntd-1; i++)
	{
		for (int j = b[d[i]][0]; j <= b[d[i]][1]; j++)
		{
			zwh[j]--;
		}
	}
	return max(n) - min(n);
	//cout << max(n) - min(n) << endl << cntd - 1 << endl;
}
//priority_queue <int, vector<int>, greater<int> > a;
int main()
{
	//zwh;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	for (int i = 1; i <= m; i++)
	{
		cin >> b[i][0] >> b[i][1];
	}
	int ans = max(n) - min(n);
	for (int i = 1; i <= n; i++)
	{
		int t = f(i);
		if (t > ans)
		{
			maxs = i;
			ans = t;
		}
	}
	cntd = 1;
	for (int i = 1; i <= m; i++)
	{
		if (b[i][0] > maxs || b[i][1] < maxs)
		{
			d[cntd++] = i;
		}
	}
	cout << ans << endl << cntd - 1 << endl;
	for (int i = 1; i <= cntd-1; i++)
	{
		cout << d[i] << " ";
	}
	//system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值