P448 校门外的树
题目链接-P448 校门外的树
解题思路
树
状
数
组
+
括
号
序
列
树状数组+括号序列
树状数组+括号序列
- 开两个树状数组分别维护左括号和右括号即可
- 我们可以把所有线段的端点看成括号序列,即 把插入的线段
[
l
,
r
]
[l,r]
[l,r]看成在坐标
l
l
l处的
(
和 r r r处的)
- 我们可以发现,最后的答案等于查询区间
[
L
,
R
]
[L,R]
[L,R]之间
(
的个数减去)
的个数 - 不懂树状数组原理的可以先去学一下
- 具体操作见代码
附上代码
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<cstring>
#include<cmath>
#include<string>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
using namespace std;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-10;
const int M=1e9+7;
const int N=5e4+5;
typedef long long ll;
typedef pair<int,int> PII;
int L[N],R[N],n;
int lowbit(int x){
return x&-x;
}
void add(int x,int d,int sum[]){//修改
while(x<=n){
sum[x]+=d;
x+=lowbit(x);
}
}
int query(int x,int sum[]){//查询
int res=0;
while(x>0){
res+=sum[x];
x-=lowbit(x);
}
return res;
}
signed main(){
int m;
scanf("%d%d",&n,&m);
while(m--){
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
if(op==1){
add(l,1,L);
add(r,1,R);
}
else
printf("%d\n",query(r,L)-query(l-1,R));
}
return 0;
}