种树

题目描述

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

 输入

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

 输出

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

 样例输入

54

1 1 3

2 2 5

1 2 4

2 3 5

样例输出

1

2

解题思路:

      这道题用树状数组极其简单,在此不解释。

      用线段树来做,要复杂一些。要建立sl,sr来记录和,实际上与树状数组中的a[2][50005]没有太大的区别。

代码:(请不要直接拷贝哦)

//树状数组
#include <cstdio>
int n,m,x,y,z,a[2][50005];
using namespace std;
inline int read()    
{    
    int f=1,x=0;    
    char ch=getchar();    
    if (ch=='-')    
    {    
        f=-1;    
        ch=getchar();    
    }    
    while ((ch<'0')||(ch>'9')) ch=getchar();    
    while ((ch>='0')&&(ch<='9'))    
    {    
        x=x*10+ch-48;    
        ch=getchar();    
    }    
    return f*x;    
}
inline void change(int x,int y)
{
	int i=x;
	while (i<=n) a[y][i]++,i+=i&(-i);
}
inline int sum(int x,int y)
{
	int i=x,s=0;
	while (i>0) s+=a[y][i],i-=i&(-i);
	return s;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        z=read(),x=read(),y=read();
        if(z==1) change(x,0),change(y,1);
        else printf("%d\n",sum(y,0)-sum(x-1,1));
    }
	return 0;
}
//线段树
#include <cstdio>
int n,m,x,y,z;
using namespace std;
struct TREE{
	int l,r;
	int sl,sr;
}tree[200005];
inline int read()    
{    
    int f=1,x=0;    
    char ch=getchar();    
    if (ch=='-')    
    {    
        f=-1;    
        ch=getchar();    
    }    
    while ((ch<'0')||(ch>'9')) ch=getchar();    
    while ((ch>='0')&&(ch<='9'))    
    {    
        x=x*10+ch-48;    
        ch=getchar();    
    }    
    return f*x;    
}
inline void build(int root,int l,int r)
{
	tree[root].l=l;
	tree[root].r=r;
	if (l==r) return;
	int mid=(l+r)/2;
	build(root*2,l,mid);
	build(root*2+1,mid+1,r);
}
inline void change_left(int root,int x)
{
	int l=tree[root].l,r=tree[root].r;
	if ((l==x)&&(r==x))
	{
		tree[root].sl++;
		return;
	}
	int mid=(l+r)/2;
	if (x<=mid) change_left(root*2,x);
	if (x>mid) change_left(root*2+1,x);
	tree[root].sl=tree[root*2].sl+tree[root*2+1].sl; 
}
inline void change_right(int root,int x)
{
	int l=tree[root].l,r=tree[root].r;
	if ((l==x)&&(r==x)) 
	{
		tree[root].sr++;
		return;
	}
	int mid=(l+r)/2;
	if (x<=mid) change_right(root*2,x);
	if (x>mid) change_right(root*2+1,x);
	tree[root].sr=tree[root*2].sr+tree[root*2+1].sr;
}
inline int find_left(int root,int l,int r)
{
	int nl=tree[root].l,nr=tree[root].r;
	int mid=(nl+nr)/2;
	if ((l<=nl)&&(nr<=r)) return tree[root].sl;
	if (l>mid) return find_left(root*2+1,l,r); else
	  if (r<=mid) return find_left(root*2,l,r); else
	    return find_left(root*2,l,r)+find_left(root*2+1,l,r);
}
inline int find_right(int root,int l,int r)
{
	int nl=tree[root].l,nr=tree[root].r;
	int mid=(nl+nr)/2;
	if ((l<=nl)&&(nr<=r)) return tree[root].sr;
	if (l>mid) return find_right(root*2+1,l,r); else
	  if (r<=mid) return find_right(root*2,l,r); else
	    return find_right(root*2,l,r)+find_right(root*2+1,l,r);
}
int main()
{
    n=read(),m=read();
    build(1,1,n);
    for (int i=1;i<=m;i++)
    {
    	z=read(),x=read(),y=read();
    	if (z==1)
    	{
    		change_left(1,x);
    		change_right(1,y);
    	} else
    	{
    		int ans=find_left(1,1,y);
    		if (x>1) ans-=find_right(1,1,x-1);
    		printf("%d\n",ans);
    	}
    }
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值