校门外的树
Time Limit:10000MS Memory Limit:65536K
Total Submit:66 Accepted:27
Case Time Limit:1000MS
Description
校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
K=1,读入l,r表示在l~r之间种上的一种树
K=2,读入l,r表示询问l~r之间能见到多少种树
(l,r>0)
Input
第一行n,m表示道路总长为n,共有m个操作
接下来m行为m个操作
Output
对于每个k=2输出一个答案
Sample Input
5 4
1 1 3
2 2 5
1 2 4
2 3 5
Sample Output
1
2
Hint
范围:20%的数据保证,n,m<=100
60%的数据保证,n <=1000,m<=50000
100%的数据保证,n,m<=50000
树状数组的区间修改:
其实就是只一段区间记录它的“head”,“tail”
若你要查询’[x,y]'中树的总种数,则就可以转化为
‘ y ’ 左 边 有 多 少 个 ‘ [ x 1 , y 1 ] ’ 的 ‘ x 1 ’ − ′ x ′ 左 边 有 多 少 ‘ [ x 1 , y 1 ] ’ 的 ‘ y 1 ’ ‘~y~’左边有多少个‘~[x^1~,y^1~]~’的‘~x^1~’~-~'~x~'左边有多少‘~[x^1~,y^1~]~’的‘~y^1~’ ‘ y ’左边有多少个‘ [x1 ,y1 ] ’的‘ x1 ’ − ′ x ′左边有多少‘ [x1 ,y1 ] ’的‘ y1 ’
如图:要查询“5~11”这个区间
则
‘
y
’
左
边
有
多
少
个
‘
[
x
1
,
y
1
]
’
的
‘
x
1
’
‘~y~’左边有多少个‘~[x^1~,y^1~]~’的‘~x^1~’
‘ y ’左边有多少个‘ [x1 ,y1 ] ’的‘ x1 ’指的是
圈起来的点,就是这段区间的颜色总种数,也就是一条线段‘ [1,y] ’的左端的个数
…………你细品……细品……
而
′
左
边
有
多
少
‘
[
x
1
,
y
1
]
’
的
‘
y
1
’
'左边有多少‘~[x^1~,y^1~]~’的‘~y^1~’
′左边有多少‘ [x1 ,y1 ] ’的‘ y1 ’指的是:
…………你细品……细品……
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <queue>
#include <cmath>
#define LL long long
using namespace std;
const int N=1e6+100,M=32005;
int n,m,s,x,y,a[N],c[N],d[N]; //c[]存左端点,d[]存右端点
int add (int x) {return x&(-x);}
void put1 (int x,int y) {for (;x<=m;x+=add (x)) c[x]+=y;}
void put2 (int x,int y) {for (;x<=m;x+=add (x)) d[x]+=y;} //Ctrl+v
int find1 (int x)
{
int ans(0);
for (;x;x-=add (x)) ans+=c[x];
return ans;
}
int find2 (int x) //Ctrl+v
{
int ans(0);
for (;x;x-=add (x)) ans+=d[x];
return ans;
}
int main ()
{
scanf ("%d %d",&m,&n);
for (int i=1;i<=n;i++)
{
scanf ("%d %d %d",&s,&x,&y);
if (s==1) put1 (x,1),put2 (y,1);
else printf ("%d\n",find1 (y)-find2 (x-1));
}
return 0;
}