分析:
查询区间内有多少不同的区间
如果一个区间的头在节点
x
x
x的左边 那这个区间包含在
[
1
,
x
]
[1,x]
[1,x] 尾也同理
线段树维护
x
x
x之前有多少区间头的数量
a
n
s
1
ans1
ans1 尾的数量
a
n
s
2
ans2
ans2 最后答案类似前缀和 即
a
n
s
2
−
a
n
s
1
ans2-ans1
ans2−ans1
CODE:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define inf 0x7fffffff
#define Inf 1e18
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,T;
struct SegmentTree{
int l,r,ansl,ansr;
}a[N<<2];
void build(int x,int l,int r)
{
a[x].l=l;a[x].r=r;
if(l==r) return;
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
}
void updateL(int x,int p)
{
if(a[x].l==a[x].r)
{
a[x].ansl++;
return;
}
if(p>a[x<<1].r) updateL(x<<1|1,p);
else updateL(x<<1,p);
a[x].ansl=a[x<<1].ansl+a[x<<1|1].ansl;
}
void updateR(int x,int p)
{
if(a[x].l==a[x].r)
{
a[x].ansr++;
return;
}
if(p>a[x<<1].r) updateR(x<<1|1,p);
else updateR(x<<1,p);
a[x].ansr=a[x<<1].ansr+a[x<<1|1].ansr;
}
int queryL(int x,int L,int R)
{
if(L<=a[x].l&&a[x].r<=R) return a[x].ansl;
if(a[x].l>R||a[x].r<L) return 0;
return queryL(x<<1,L,R)+queryL(x<<1|1,L,R);
}
int queryR(int x,int L,int R)
{
if(L<=a[x].l&&a[x].r<=R) return a[x].ansr;
if(a[x].l>R||a[x].r<L) return 0;
return queryR(x<<1,L,R)+queryR(x<<1|1,L,R);
}
int main()
{
scanf("%d%d",&n,&T);
build(1,1,n);
while(T--)
{
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
if(op==1)
{
updateL(1,l);
updateR(1,r);
}
if(op==2)
{
int R=queryL(1,1,r);
int L=queryR(1,1,l-1);
printf("%d\n",R-L);
}
}
return 0;
}