时间: 1000ms / 空间: 131072KiB / Java类名: Main
描述
校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
K=1,读入l,r表示在l~r之间种上的一种树
K=2,读入l,r表示询问l~r之间能见到多少种树
(l,r>0)
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
K=1,读入l,r表示在l~r之间种上的一种树
K=2,读入l,r表示询问l~r之间能见到多少种树
(l,r>0)
输入格式
第一行n,m表示道路总长为n,共有m个操作
接下来m行为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号位置上可以种多种树
60%的数据保证,n <=1000,m<=50000
100%的数据保证,n,m<=50000
注意:树是可以重叠的,比如1号位置上可以种多种树
树状数组
开两个树状数组,一个记录起点,一个记录终点。
一个区间内树的种类=起点小于区间末尾的树的种数-终点小于区间头的树的种数
(也可以用线段树)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int n,m; 6 int t[2][50010]; 7 void add(int a,int x,int v){ 8 while(x<=n){ 9 t[a][x]+=v; 10 x+=x&-x; 11 } 12 return; 13 } 14 int smm(int a,int x){ 15 int res=0; 16 while(x){ 17 res+=t[a][x]; 18 x-=x&-x; 19 } 20 return res; 21 } 22 int main(){ 23 scanf("%d%d",&n,&m); 24 int i,j,op,x,y; 25 while(m--){ 26 scanf("%d%d%d",&op,&x,&y); 27 if(op==1){ 28 add(0,x,1); 29 add(1,y,1); 30 } 31 else{ 32 int ans=smm(0,y)-smm(1,x-1); 33 printf("%d ",ans); 34 } 35 } 36 return 0; 37 }