贪婪大陆——(树状数组)
面对蚂蚁们的疯狂进攻,小 FF 的 Tower defence 宣告失败……人类被蚂蚁们逼到了Greed Island 上的一个海湾。现在,小 FF 的后方是一望无际的大海, 前方是变异了的超级蚂蚁。 小 FF 还有大好前程,他可不想命丧于此, 于是他派遣手下最后一批改造 SCV布置地雷以阻挡蚂蚁们的进攻。
小 FF 最后一道防线是一条长度为 N 的战壕, 小 FF 拥有无数多种地雷,而 SCV 每次可以在[ L , R ]区间埋放同一种不同于之前已经埋放的地雷。 由于情况已经十万火急,小FF 在某些时候可能会询问你在[ L’ , R’] 区间内有多少种不同的地雷, 他希望你能尽快的给予答复。
输入
第一行为两个整数 n 和 m; n 表示防线长度, m 表示 SCV 布雷次数及小 FF 询问 的次数总和。
接下来有 m 行, 每行三个整数 Q,L , R;
若 Q=1 则表示 SCV 在[ L , R ]这段区间 布上一种地雷,
若 Q=2 则表示小 FF 询问当前[ L , R ]区间总共有多少种地雷。
输出
对于小 FF 的每次询问,输出一个答案(单独一行),表示当前区间地雷总数
样例输入
5 4
1 1 3
2 2 5
1 2 4
2 3 5
样例输出
1
2
提示
【数据范围】
对于 30%的数据: 0<=n, m<=1000;
对于 100%的数据: 0<=n, m<=10^5.
本来以为是维护区间加1区间最值查询,但果然错了
要维护的是区间种类查询
可以这样做
把左区间和右区间分别当作左括号和右括号,那么每一个左括号就是一个区间的开始,每一个右括号就是一个区间的结束
那么对于每一个查询的区间,那么区间中地雷的个数就是1—r中左括号的个数(也就是前面埋了有多少种地雷)减去1–(l-1)中右括号的个数(也就是前面埋完了多少种地雷)
那我们只需要两个树状数组来分别维护左括号和右括号就是了
代码
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0;
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res;
}
int t1[100005],t2[100005],n,m;
inline int lowbit(int k)
{
return k&(-k);
}
inline int add(int l,int r)
{
while(l<=n)
{
t1[l]++;
l+=lowbit(l);
}
while(r<=n)
{
t2[r]++;
r+=lowbit(r);
}
}
inline int query(int l,int r)
{
l--;
int ans1=0,ans2=0;
while(r>0)
{
ans1+=t1[r];
r-=lowbit(r);
}
while(l>0)
{
ans2+=t2[l];
l-=lowbit(l);
}
return ans1-ans2;
}
int main(){
n=read(),m=read();
int q,l,r;
for(int i=1;i<=m;i++)
{
q=read(),l=read(),r=read();
if(q==1) add(l,r);
else cout<<query(l,r)<<'\n';
}
return 0;
}