原题链接
标签:贪心,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;
}