贪心:最大相交区间

题目:http://acm.zcmu.edu.cn/JudgeOnline/problem.php?id=1892

这题快搞疯我了,一开始以为直接排序然后取相邻,后来发现不行。
在询问了大佬之后大佬给讲了一下,茅塞顿开,顿时觉得我可能长了个假脑。

在找两组的时候,即k = 2时,排序区间左端点,维护最大区间右端点,有以下递推式:

第i个区间[a,b]:
ans = max(ans, min(maxr, b) - a + 1);
maxr = max(maxr, b);

同样的,当k可以去任意数时,我们只需要将维护最大区间右端点改成维护第k - 1大区间右端点即可
维护方法:用小根堆维护k - 1个数,如果新的区间右端点比小根堆堆顶元素要大,那就交换一下再维护一下小根堆

然后vs上的max和min貌似用不了,就手写了一个

有思路以后又wa了一次,原因是我在最后输出ans + 1,没有考虑到答案为0(区间都不重复)的情况
改了以后又RE了,原因是没有考虑到k == 1的情况即small.top()不存在,于是加上了判断k == 1
然后就喜闻乐见的超时了。。。手打的快排竟然撑不过300000。。。我也是ri le gou le。。。
学了一下sort的结构体用法以后,终于ac了。。。

代码如下:

#include 
#include 
#include         //sort
#include             //根堆
#include        //小根堆里的greater

using namespace std;

struct RULER {
    int x;
    int y;
}ruler[400000] = { 0 };

int max(int a, int b)       //vs上的max和min貌似用不了
{
    return a > b ? a : b;
}

int min(int a, int b)
{
    return a < b ? a : b;
}

bool comparison(struct RULER l, struct RULER r)     //结构体排序的参数
{
    return l.x < r.x;
}

/*void Sort(int l, int r)           //一开始手打排序,结果莫名其妙才300000就超时了...
{
    if (l >= r)
        return;
    int pivot = ruler[l].x;
    int pivotors = l;
    for (int i = l + 1; i <= r; i++)
    {
        if (ruler[i].x < pivot) {
            pivotors++;
            swap(ruler[pivotors], ruler[i]);
        }
    }
    swap(ruler[l], ruler[pivotors]);
    Sort(l, pivotors - 1);
    Sort(pivotors + 1, r);
}*/

int main()
{
    int n, k;
    cin >> n >> k;
    for (int i = 0; i < n; i++)
        scanf("%d%d", &ruler[i].x, &ruler[i].y);

    sort(ruler, ruler + n, comparison);

    priority_queue<int, vector<int>, greater<int> > small;
    for (int i = 0; i < k - 1; i++)
        small.push(ruler[i].y);

    int ans = 0, maxr;
    //maxr = small.top();   没有考虑k == 1的情况
    if (k == 1)
        maxr = 2000000000;
    else
        maxr = small.top();
    for (int i = k - 1; i < n; i++) {
        ans = max(ans, min(maxr, ruler[i].y) - ruler[i].x + 1);
        if (ruler[i].y > maxr) {
            small.pop();
            small.push(ruler[i].y);
            maxr = small.top();
        }
    }

    cout << ans << endl;

    return 0;
}

顺便给自己做个关于根堆和快排的笔记:

priority_queue<int>     //xxx 大根堆   #include 
priority_queue<int, vector<int>, greater<int>>  //xxxx 小根堆  #include  #include 
xxx.top()   //访问最值
xxx.push()  //插入最值(插入后自动维护)
xxx.pop()   //删除最值(删除后自动维护)
#include 
bool comparison(struct RULER l, struct RULER r)
{
    return l.x < r.x;   //从小到大
}
sort(ruler, ruler + n, comparison);

顺便贴一下一个相似题的一解题报告:http://blog.csdn.net/chj_zmr/article/details/8800313

最后感谢一下那个教我题大佬顺便膜一发orz

你可能感兴趣的:(c++)