Codeforces 31C Schedule(数据结构)

Schedule
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
At the beginning of the new semester there is new schedule in the Berland State University. According to this schedule, n groups have lessons at the room 31. For each group the starting time of the lesson and the finishing time of the lesson are known. It has turned out that it is impossible to hold all lessons, because for some groups periods of their lessons intersect. If at some moment of time one groups finishes it’s lesson, and the other group starts the lesson, their lessons don’t intersect.

The dean wants to cancel the lesson in one group so that no two time periods of lessons of the remaining groups intersect. You are to find all ways to do that.

Input
The first line contains integer n (1 ≤ n ≤ 5000) — amount of groups, which have lessons in the room 31. Then n lines follow, each of them contains two integers li ri (1 ≤ li < ri ≤ 106) — starting and finishing times of lesson of the i-th group. It is possible that initially no two lessons intersect (see sample 1).

Output
Output integer k — amount of ways to cancel the lesson in exactly one group so that no two time periods of lessons of the remaining groups intersect. In the second line output k numbers — indexes of groups, where it is possible to cancel the lesson. Groups are numbered starting from 1 in the order that they were given in the input. Output the numbers in increasing order.

Examples
input
3
3 10
20 30
1 3
output
3
1 2 3
input
4
3 10
20 30
1 3
1 39
output
1
4
input
3
1 5
2 6
3 7
output
0

题目大意:
就是n个组要在某个教室上课,但是上课时间不能重叠,问去掉一个组的课程就可以使得其他n-1个组的课程不重叠的方案有几种,并按照从小到大的顺序输出这些组号

题目分析:
最开始以为是贪心中的区间问题,但是后来发现这个就是一道数据结构的设计问题,我是这样设计的,一个四元组来存储每个组的信息
{组号,开始时间,结束时间,重叠次数}
这里的重叠次数指的是当前组和其他组的重叠的次数
然后对这n个组的信息按照起始时间进行从小到大的排序,
接下来就开始要对每个组的重叠次数进行统计,如果相邻两个组的时间没有重叠,那么他们两个组的重叠次数没有变化,如果相邻两个组有重叠,并且第三个组跟着两个组的重叠部分没有公共部分的话,那么对每个组的重叠次数加上1,整个的重叠次数也减去1
在接下来就是搜结果了,如果整个的重叠次数减去当前组的重叠次数等于零的话,说明去掉当前组的话可以满足条件,那么就把当前的组号压进优先队列,如果不是0,就不满足啦
当然我这里说的只是思路,具体实现的话需要细节支持,接下来看代码吧。

代码:

#include "stdio.h"
#include "algorithm"
#include "string.h"
#include "queue"
using namespace std;
struct node
{
    int l,r,c,no;
};
node t[5000+5];

bool cmp(node a,node b)
{
    if(a.l==b.l) return a.r<b.r;
    return a.l<b.l;
}
int main()
{
    int n,i,total,res;
    while(scanf("%d",&n)!=EOF)
    {
        memset(t,0,sizeof(t));
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&t[i].l,&t[i].r);
            t[i].c=0;
            t[i].no=i+1;
        }
        sort(t,t+n,cmp);
        total=res=0;
        int r=t[0].r,cur=0;
        bool flag=false;
        for(i=1;i<n;i++)
        {
            //cur指的是当前与后面组进行比较的组,含义的话只能去体会了
            if(t[i].l<r){
                if(i<n-1&&t[i+1].l<min(r,t[i].r)){
                    flag=true;
                    break;
                }else{
                    t[cur].c++;
                    t[i].c++;
                    if(t[i].r>=r){
                        cur=i;
                        r=t[i].r;
                    }
                    total++;
                }
            }else{
                cur=i;
                r=t[i].r;
            }
        }
        if(flag){
            printf("0\n");
        }else{
            priority_queue<int,vector<int>,greater<int> > que;
            for(i=0;i<n;i++)
            {
                //printf("%d\n",t[i].c);
                if(total-t[i].c==0){
                    que.push(t[i].no);
                    res++;
                }
            }
            printf("%d\n",res);
            while(!que.empty()){
                if(que.size()!=1){
                    printf("%d ",que.top());
                }else{
                    printf("%d\n",que.top());
                }
                que.pop();
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值