校门外有很多树 线段覆盖问题

NKOJ1317 校门外有很多树

问题描述

校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
K=1,读入l,r表示在l~r之间种上的一种树 K=2,读入l,r表示询问l~r之间能见到多少种树(1<=l<=r<=n)

输入格式

第一行n,m表示道路总长为n,共有m个操作 接下来m行为m个操作

输出格式

对于每个k=2输出一个答案

样例输入

5 4
1 1 3
1 2 4
2 3 5

样例输出

1
2

提示

20%的数据保证,n,m<=100 60%的数据保证,n <=1000,m<=50000 100%的数据保证,n,m<=50000


显然是线段覆盖问题。

如果询问是放在所有种树操作之后的,那么我们可以采用离线算法,用差分数组实现O(n)的时间复杂度。然而这道题必须采用在线算法,用差分数组肯定会TLE。

然而这道题还是很水。我们可以用树状数组解决问题。

这里写图片描述

询问L到R区间内的线段数目S,显然满足:S=起点在[1,R]内的线段总数-终点在[1,L-1]的线段总数。
因此用树状数组维护两个数组即可。

#include<stdio.h>
int C[2][50005],N,M;
int GetSum(int x,int k)
{
    int i,sum=0;
    for(i=x;i;i-=(i&-i))sum+=C[k][i];
    return sum;
}
void ModiFy(int x,int k){for(int i=x;i<=N;i+=(i&-i))C[k][i]++;}

int main()
{
    int i,x,y,k;

    scanf("%d%d",&N,&M);
    for(i=1;i<=M;i++)
    {
        scanf("%d%d%d",&k,&x,&y);
        if(k==1)ModiFy(x,0),ModiFy(y,1);
        else printf("%d\n",GetSum(y,0)-GetSum(x-1,1));
    }
}

线段树当然也可以,但显然优选树状数组。也有用线段树维护区间重复部分的算法,由于不够优秀,这里不再讨论。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值