51nod 1631 小鲨鱼在51nod小学 【线段树--】

基准时间限制: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<string.h>
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
struct node{
    int l,r;
    vector<int> hao;
}pp[1050000];
int nian[1010],month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31},ans;
int pre[220],ll;
bool run(int x)
{
    if (x%400==0||(x%100&&x%4==0)) return true;
    return false;
}
void ss()
{
    nian[0]=month[0]=0;
    for (int i=1;i<=1000;i++)
    {
        if (run(i+1999))
            nian[i]=nian[i-1]+366;
        else
            nian[i]=nian[i-1]+365;
    }
}
int gg(int y,int m,int d)
{
    if (run(y))
        month[2]=29;
    else
        month[2]=28;
    int ans=nian[y-2000];
    for (int i=1;i<m;i++)
        ans+=month[i];
    ans+=d;
    return ans;
}
void create(int l,int r,int x)
{
    ans=max(ans,x);
    pp[x].l=l;pp[x].r=r;
    if (l==r) return ;
    int m=(l+r)>>1;
    create(l,m,x*2);
    create(m+1,r,x*2+1);
}
void query(int l,int r,int h,int x)
{
    if (l==pp[x].l&&r==pp[x].r)
    {
        pp[x].hao.push_back(h);
        return ;
    }
    int m=(pp[x].l+pp[x].r)>>1;
    if (r<=m)
        query(l,r,h,x*2);
    else if (l>m)
        query(l,r,h,x*2+1);
    else
    {
        query(l,m,h,x*2);
        query(m+1,r,h,x*2+1);
    }
}
void search_hao(int l,int x)
{
    for (int i=0;i<pp[x].hao.size();i++)
        pre[ll++]=pp[x].hao[i];
    if (pp[x].l==pp[x].r) return ;
    int m=(pp[x].l+pp[x].r)>>1;
    if (l>m)
        search_hao(l,x*2+1);
    else
        search_hao(l,x*2);
}
int main()
{
    int n,q,y1,y2,m1,m2,d1,d2,a,l,r;
    scanf("%d",&n);ss();ans=0;
    create(1,365243,1);
    for (int i=0;i<n;i++)
    {
        scanf("%d%d%d%d%d%d%d",&y1,&m1,&d1,&y2,&m2,&d2,&a);
        if (run(y2))
            month[2]=29;
        else month[2]=28;
        if ((y1<y2-1)||(y1<y2&&m2+12>m1+1)||(y1<y2&&d2>=d1)||(y1==y2&&(m1+1<m2||(m1+1==m2&&d2>=d1))))
        {
            l=gg(y1,m1,d1);
            r=gg(y2,m2,d2);
            query(l,r,a,1);
        }
    }
    scanf("%d",&q);
    for (int i=0;i<q;i++)
    {
        scanf("%d%d%d",&y1,&m1,&d1);
        l=gg(y1,m1,d1);
        ll=0;
        search_hao(l,1);
        sort(pre,pre+ll);
        printf("%d",ll);
        for (int i=0;i<ll;i++)
            printf(" %d",pre[i]);
        printf("\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值