题意:有两台电视,有n个节目,每个节目有各自的播放时间,判断能否用两台电视将所有节目都看完,两个节目若一节目结束时间和另一节目开始时间相同,它们需要在两个电视观看。
看了别人的题解,感觉自己的想法实在是不行,直接对两个电视工作情况进行模拟更好一些。
思路:就是找会不会有哪一个时间有三个或三个以上的节目在播放。因为三个就不行了所以我们只要找三个就行了。对每一个节目都找覆盖在其内的节目,贪心,先对所有节目进行排序,开始时间由小到大,若开始时间相同则结束时间由小到大。从前到后遍历,只用找在该节目之前播出的最迟结束的两个节目(用优先队列可以得到两个之前播出的最大的结束时间)和在该节目播出后的最早播放的两个节目(就是在该节目播放后的两个节目,以及排好序的),看其重合部分(要仔细考虑重合的部分到底在哪)。
写的时候很多问题没有注意到,昨天改了又改,本来以为终于对了结果今天早上起来就被hack了
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<queue> #include<functional> using namespace std; #define LL long long const LL maxn = 2*1e5; struct node { LL st,ed; }a[maxn+5]; LL n; bool cmp(node a,node b) { if(a.st==b.st) return a.ed<b.ed; return a.st<b.st; } int main() { while(scanf("%lld",&n)!=EOF) { memset(a,0,sizeof a); for(int i=0;i<n;i++) scanf("%lld%lld",&a[i].st,&a[i].ed); sort(a,a+n,cmp); int flag = 0; priority_queue<LL,vector<LL>,less<LL> >q; while(!q.empty()) q.pop(); q.push(a[0].ed),q.push(a[1].ed); for(int i=2;i<n;i++) { LL t = q.top(),cnt1 = 0,cnt = 0; q.pop(); if(t>=a[i].st) cnt1++;//|_____|_____| ,其中第一个|和最后一个|代表第i个节目的开始和结束时间,中间的|代表之前播出的最迟的结束时间,画的是满足条件的情况,其中重复的部分是第1个|到第二个|之间。 if(q.top()>=a[i].st) cnt1++;//|___|_|_____|,这里也是画满足条件的情况,其中重复的部分也是第1个|到第二个|之间。 if(i+1<n&&a[i+1].st<=a[i].ed) cnt++;// if(i+2<n&&a[i+2].st<=a[i].ed&&a[i+2].st<=a[i+1].ed) cnt++;//要考虑到上一个结束时间较早的情况,如:|_!___!_#__#_|,其中!代表下面第一个节目,#代表第二个 if((cnt&&a[i+1].st<=t)||cnt>=2||cnt1>=2)//后面的和前面的重合,前面的和前面的重合,后面的和后面的重合 { flag = 1; break; } q.push(t); q.push(a[i].ed); } if(flag) printf("NO\n"); else printf("YES\n"); } return 0; }