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