SUDTOJ 3323园艺问题 (线段树)

园艺问题
Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述

本巨养了一盆双色茉莉。这种花有一种特点:第i朵花在第Di天盛开,刚开时是紫色的,Ai天之后会变成白色,再过Bi天就会凋谢。如Di = 3,Ai = 4,Bi = 5,那么在第3至6天为紫色,第7至11天为白色,第11天之后就凋谢了。

现在给出一些事件,你需要按要求给出答案。

事件1:在第Di天开了一朵花,这朵花Ai天后变成白色,再过Bi天就会凋谢。

事件2:询问在第X天时,紫色花朵和白色花朵各有多少。
输入

输入包含多组。对于每组数据:

第一行包含一个整数n (1 <= n <= 300,000)。

接下来的n行,为下述两种格式的一种,分别代表事件1和事件2。

1 Di Ai Bi

2 X

对于所有数据有:1 <= Di,Ai,Bi <= 1,000,000,000 ,1 <= Ai <= 3,000,000,000;
输出

对于每个事件2输出一行,包含两个整数代表答案。
示例输入

4
1 3 2 3
2 4
1 2 1 1
2 10

示例输出

1 0
0 0
周赛的时候没有想到可以先全部输入进行离散化,再进行建树,我啸的一句话惊醒了我

#include <bits/stdc++.h>
#define LL long long
#define esp 1e-8
#define INF 0x3f3f3f3f
#define Fread() freopen("../in.in","r",stdin)
#define Fwrite() freopen("../out.out","w",stdout)

using namespace std;

const int Max = 301000;

typedef struct Flow
{
    LL l,r,L,R;
}Flow;

union Flower
{
    Flow F;
    LL Q;
};
typedef struct Seg
{
    int sum1;
    int sum2;
} Tree;
int Sta[Max];
Flower FF[Max];
Tree T[Max*5];
LL Da[Max*2];
int top2,top3;
LL a,b,d;
int c;
int num1,num2;
void Update_down(int site,int L,int R)//向下更新
{
    if(L==R)
    {
        return ;
    }
    T[site<<1].sum1+=T[site].sum1;
    T[site<<1].sum2+=T[site].sum2;
    T[site<<1|1].sum1+=T[site].sum1;
    T[site<<1|1].sum2+=T[site].sum2;
    T[site].sum1=T[site].sum2=0;
}
void Build(int L,int R,int site)//建树
{
    T[site].sum1=0;
    T[site].sum2=0;
    if(L==R)
    {
        return ;
    }
    int mid=(L+R)>>1;
    Build(L,mid,site<<1);
    Build(mid+1,R,site<<1|1);
}
void Update(int L,int R,int l,int r,int site,int ans)//更新
{

    if(L==l&&R==r)
    {
        if(ans==1)
        {
            T[site].sum1++;
        }
        else
        {
            T[site].sum2++;
        }
        return ;
    }
    int mid=(L+R)>>1;
    if(r<=mid)
    {
        Update(L,mid,l,r,site<<1,ans);
    }
    else if(l>mid)
    {
        Update(mid+1,R,l,r,site<<1|1,ans);
    }
    else
    {
        Update(L,mid,l,mid,site<<1,ans);
        Update(mid+1,R,mid+1,r,site<<1|1,ans);
    }
}
void Query(int L,int R,int x,int site)//查询
{
    if(L==R)
    {
        num1=T[site].sum1;
        num2=T[site].sum2;
        return ;
    }
    Update_down(site,L,R);
    int mid=(L+R)>>1;
    if(x<=mid)
    {
        Query(L,mid,x,site<<1);
    }
    else
    {
        Query(mid+1,R,x,site<<1|1);
    }

}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        vector<LL>Arr;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&Sta[i]);
            if(Sta[i]==1)
            {
                scanf("%lld %lld %lld",&d,&a,&b);
                FF[i].F.l=d;
                FF[i].F.r=d+a-1;
                FF[i].F.L=d+a;
                FF[i].F.R=d+a+b-1;
                Arr.push_back(d);
                Arr.push_back(d+a-1);
                Arr.push_back(d+a);
                Arr.push_back(d+a+b-1);
            }
            else
            {
                scanf("%lld",&FF[i].Q);
                Arr.push_back(FF[i].Q);
            }
        }
        sort(Arr.begin(),Arr.end());
        Arr.erase(unique(Arr.begin(),Arr.end()),Arr.end());//去重
        int ans=0;
        map<LL,int>Ma;
        for(int i=0; i<Arr.size(); i++)
        {
            Ma[Arr[i]]=++ans;//编号
        }
        Build(1,ans,1);
        for(int i=1;i<=n;i++)
        {
            if(Sta[i]==1)
            {
                Update(1,ans,Ma[FF[i].F.l],Ma[FF[i].F.r],1,1);
                Update(1,ans,Ma[FF[i].F.L],Ma[FF[i].F.R],1,2);
            }
            else
            {
                num1=num2=0;
                Query(1,ans,Ma[FF[i].Q],1);
                printf("%d %d\n",num1,num2);
            }
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/juechen/p/5255915.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值