您的位置:首页 > 运维架构

openjudge 校门外的树3

2016-01-11 19:53 393 查看
P1473 校门外的树3

时间: 1000ms / 空间: 131072KiB / Java类名: Main


描述

校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……

如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:

K=1,读入l,r表示在l~r之间种上的一种树

K=2,读入l,r表示询问l~r之间能见到多少种树

(l,r>0)


输入格式

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

接下来m行为m个操作


输出格式

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


测试样例1


输入

5 4

1 1 3

2 2 5

1 2 4

2 3 5


输出

1

2


备注

范围:20%的数据保证,n,m<=100

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

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

注意:树是可以重叠的,比如1号位置上可以种多种树

此题是一道不错的线段树题,做题前一定要想清楚,如果一个区间的左右子树都含有同一种树,那么对于这个区间绝不是1+1=2,而还应该是1,所以我们需要一个数组去记录左右子树相同树的个数。

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<cmath>

using namespace std;

int a[2000000],i,j,n,m,p[2000000],s[2000000];

void pushdown(int now,int l,int r,int mid)

{

if (s[now]!=0)//下放时一定要想明白,既然可以下放则说明他的左右子树有,需要更新p数组

{

s[now<<1]+=s[now];

s[(now<<1)+1]+=s[now];

a[now<<1]+=s[now];

a[(now<<1)+1]+=s[now];

p[now<<1]+=s[now];

p[(now<<1)+1]+=s[now];

s[now]=0;

}

}

void qchange(int now,int l,int r,int ll,int rr)

{

if (l>=ll&&rr>=r)

{

s[now]+=1;

a[now]++;

p[now]++;

return ;

}

int mid=(l+r)/2;

pushdown(now,l,r,mid);

a[now]++;

int pd1=0,pd2=0;

if (ll<=mid)

{

qchange(now<<1,l,mid,ll,rr);

pd1=1;

}

if (rr>mid)

{

qchange((now<<1)+1,mid+1,r,ll,rr);

pd2=1;

}

if (pd1==1&&pd2==1)

p[now]++;

}

int qsum(int now,int l,int r,int ll,int rr)

{

int mid=(l+r)/2;

pushdown(now,l,r,mid);

if (ll<=l&&rr>=r)

{

return a[now];

}

int ans=0;

int pd1=0,pd2=0;

if (ll<=mid)

ans+=qsum(now<<1,l,mid,ll,rr),pd1=1;

if (rr>mid)

ans+=qsum((now<<1)+1,mid+1,r,ll,rr),pd2=1;

if (pd1==1&&pd2==1)

return ans-p[now];

else

return ans;

}

int main()

{

//freopen("a.in","r",stdin);

scanf("%d%d",&n,&m);

for (i=1;i<=m;i++)

{

int x,y,z;

scanf("%d%d%d",&x,&y,&z);

if (x==1)

{

qchange(1,1,n,y,z);

}

else

{

printf("%d\n",qsum(1,1,n,y,z));

}

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: