CodeForces754D【贪心】

题意:
有n个区间,每个区间覆盖区间里一段数,求最大连续区间长度被覆盖k次,并输出选取的区间。
思路:
贪心;
感觉一开始肯定是要把区间按left从小到大排序的。
然后肯定是连续k个区间能够达到的重叠最长?
因为left已经足够小了?
3 2
1 100
30 70
31 78
这个案例就说明这样贪心还不是准确的。
其实不管k多大,只有一个left,一个right,left大,right小这样是最差的,也是最长的最小。
现在就是进来的时候,left就是很大啊!
然后只要考虑right是不是又特别小。ok!!!!就是这样啊!!
用优先队列维护right,队列头的right最小就好了

//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=3e5+10;
struct asd{
    int left,right,id;
    friend bool operator< (asd n1,asd n2)
    {
        return n1.right>n2.right;
    }
};
bool cmp(asd n1,asd n2)
{
    if(n1.left==n2.left) return n1.right<n2.right;
    return n1.left<n2.left;
}
asd now[N];
priority_queue<asd>q;
int main()
{
    int n,k,s,t;
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&s,&t);
        now[i].left=s;
        now[i].right=t;
        now[i].id=i+1;
    }
    int ans,rightmin,leftmax;
    sort(now,now+n,cmp);
    ans=0; 
    for(int i=0;i<n;i++)
    {
        q.push(now[i]);
        if(q.size()>k)
            q.pop();
        if(q.size()==k)
        {
            leftmax=now[i].left;
            if((q.top().right-leftmax+1)>ans)
            {
                ans=q.top().right-leftmax+1;
                rightmin=q.top().right;
            }
        }
    }
    printf("%d
",ans);
    if(ans==0)
        for(int i=1;i<=k;i++)
            printf("%d ",i);
    else
        for(int i=0;i<n;i++)
            if(k&&now[i].left<=leftmax && now[i].right>=rightmin){ 
                    printf("%d ",now[i].id);
                    k--;
        		} 
    return 0;
}


原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777423.html