1631 小鲨鱼在51nod小学

100 篇文章 0 订阅
88 篇文章 0 订阅

基准时间限制:1 秒 空间限制:131072 KB 分值: 20  难度:3级算法题
 收藏
 关注
鲨鱼巨巨2.0(以下简称小鲨鱼)以优异的成绩考入了51nod小学。并依靠算法方面的特长,在班里担任了许多职务。

每一个职务都有一个起始时间A和结束时间B,意为小鲨鱼在[A, B]时间内,担任了某职务(inclusively)。

现在给定小鲨鱼的职务履历表,你可以高效的给出小鲨鱼在某天担任了哪些职务吗?

p.s. 由于小鲨鱼担任的职务太多,所有任期小于一个自然月的职务都忽略不计。(如1月1日~2月1日为一个自然月,即月份加1)

p.p.s. 输入数据保证小鲨鱼同时不担任超过200种职务。(牛!)

p.p.p.s 输入的日期均为合法日期,范围在2000年01月01日~2999年12月31日。

p.p.p.p.s 巨大的输入输出,推荐使用scanf/printf,编译器推荐使用Virtual C++
Input
第一行为一个整数n,代表小鲨鱼担任过N种职务。(1 <= n <= 10^5)
接下来的n行,每一行为七个整数,y0, m0, d0, y1, m1, d1, x。意为在<y0, m0, d0>到<y1, m1, d1>时间内,小鲨鱼担任了职务x。(1 <= x <= 10^9)
给定的时间皆合法,且起始日期小于或等于截止日期。职务x是唯一的。

接下来是一个整数q,代表q次查询。(1 <= q <= 10^4)
接下来的q行,每一行为三个整数<y, m, d>,代表查询的日期。时间皆合法。
Output
每一次查询输出一行结果。
首先输出一个整数n,代表此时小鲨鱼担任的职务数。(n可以为0)
接下来是n个整数,代表小鲨鱼担任的职务。职务列表保持升序。
Input示例
4
2000 01 01    2000 01 01    111
2000 01 02    2001 02 02    222
2000 01 28    2000 02 29    333
2000 01 29    2000 02 28    444
4
2000 01 01
2000 01 02
2000 01 28
2000 02 29
Output示例
0
1 222
2 222 333
2 222 333

思路:

先筛选,再用线段的思想扫一下


#include <cstdio>
#include<cstring>
#include <vector>
#include <algorithm>
#include <queue>
using  namespace std;
const int maxn=100005;
struct node
{
    int yl,yr,ml,mr,dl,dr;
    int num;
    bool operator <(const struct node &r) const
    {
        return r.num<num;
    }
}data[maxn];
int cmp(node x,node y)
{
    if(x.yl!=y.yl)
        return x.yl<y.yl;
    if(x.ml!=y.ml)
        return x.ml<y.ml;
    if(x.dl!=y.dl)
        return x.dl<y.dl;
    return x.num<y.num;
}
int cmpl(node x,int y,int m,int d)
{
    if(x.yl>y)
        return 0;
    if(x.yl==y)
    {
        if(x.ml>m)
            return 0;
        if(x.ml==m&&x.dl>d)
            return 0;
    }
    return 1;
}
int cmpr(node x,int y,int m,int d)
{
    if(x.yr<y)
        return 0;
    if(x.yr==y)
    {
        if(x.mr<m)
            return 0;
        if(x.mr==m&&x.dr<d)
            return 0;
    }
    return 1;
}
int cmpok(int y,int y1,int m,int m1,int d,int d1)
{
    if(y==y1)
    {
        if(m==m1)
            return 0;
        if(m==m1-1&&d>d1)
            return 0;
    }
    else
    {
        if(y1-y>1)
            return 1;
        if(m==12&&m1==1)
        {
            if(d>d1)
                return 0;
        }
    }
    return 1;
}
int main()
{
    int n;
    scanf("%d",&n);
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        int y,y1,m,m1,d,d1,mm;
        scanf("%d%d%d%d%d%d%d",&y,&m,&d,&y1,&m1,&d1,&mm);
        if(cmpok(y,y1,m,m1,d,d1)==0)
            continue;
        cnt++;
        data[cnt].yl=y;
        data[cnt].yr=y1;
        data[cnt].ml=m;
        data[cnt].mr=m1;
        data[cnt].dl=d;
        data[cnt].dr=d1;
        data[cnt].num=mm;
    }
    sort(data+1,data+1+cnt,cmp);
    int q;
    scanf("%d",&q);
    while(q--)
    {
        int y,m,d;
        scanf("%d%d%d",&y,&m,&d);
        priority_queue<node > q;
        for(int i=1;i<=cnt;i++)
        {
            if(cmpl(data[i],y,m,d)==0)
                break;
            if(cmpr(data[i],y,m,d)==0)
                continue;
            q.push(data[i]);
        }
        printf("%d",q.size());
        if(!q.empty())
        {
        while(!q.empty())
        {
            printf(" %d",q.top().num);
            q.pop();
        }
        }
        printf("\n");
    }
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值