校门外的树
描述
校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
K=1,K=1,读入l、r表示在区间[l,r]中种上一种树,每次操作种的树的种类都不同
K=2,读入l,r表示询问l~r之间能见到多少种树
(l,r>0)
格式
输入格式
第一行n,m表示道路总长为n,共有m个操作
接下来m行为m个操作
输出格式
对于每个k=2输出一个答案
样例1
样例输入1
5 4
1 1 3
2 2 5
1 2 4
2 3 5
样例输出1
1
2
限制
1s
提示
范围:20%的数据保证,n,m<=100
60%的数据保证,n <=1000,m<=50000
100%的数据保证,n,m<=50000
来源
dejiyu@CSC WorkGroup
分析:
最大区间覆盖的模板题。
如果是区间修改和单点查询,那么我们在修改的时候只要$update(l,1),update(r+1,-1)$就行了,也就是说先从$l$开始$+1$,再从$r+1$开始$-1$,也就保证了只有$[l,r]$被修改。但这题是区间修改与区间查询,因此我们采用开两个树状数组的方法,一个记录$l$的修改,一个记录$r$的修改。
Code:
//It is made by HolseLee on 3rd Sep 2018 //Vijos 1448 #include<bits/stdc++.h> using namespace std; const int N=5e4+7; int n,m,c[N],b[N]; inline int read() { char ch=getchar(); int num=0; bool flag=false; while( ch<'0' || ch>'9' ) { if( ch=='-' ) flag=true; ch=getchar(); } while( ch>='0' && ch<='9' ) { num=num*10+ch-'0'; ch=getchar(); } return flag ? -num : num; } inline int lowbit(int x) { return x&(-x); } inline void update1(int x) { for(; x<=n; x+=lowbit(x)) c[x]++; } inline void update2(int x) { for(; x<=n; x+=lowbit(x)) b[x]++; } inline int quary1(int x) { int ret=0; for(; x>0; x-=lowbit(x)) ret+=c[x]; return ret; } inline int quary2(int x) { int ret=0; for(; x>0; x-=lowbit(x)) ret+=b[x]; return ret; } int main() { n=read(); m=read(); int opt,x,y; for(int i=1; i<=m; ++i) { opt=read(), x=read() ,y=read(); if( opt==1 ) { update1(x); update2(y); } else { printf("%d ",quary1(y)-quary2(x-1)); } } return 0; }