链接:https://ac.nowcoder.com/acm/contest/1108/H
Description
Bobo 精通数据结构!他想维护一个线段的集合 S。初始时,S 为空。他会依次进行 q 次操作,操作有 2 种。
- 类型 1:给出 l, r,向集合 S 中插入线段 [l, r].
- 类型 2:给出 l, r,询问满足 [x, y]∈S 且 x ≤ l ≤ r ≤ y 的线段 [x, y] 数量。
帮 Bobo 求出每次询问的答案。
- 1 ≤ n, q ≤ 105
- ti ∈ {1, 2}
- 1 ≤ li ≤ ri ≤ n
- 对于 ti = 2 的操作,ri − li ≤ 2 成立。
- 数据组数不超过 10.
Input
输入文件包含多组数据,请处理到文件结束。
每组数据的第一行包含 2 个整数 n 和 q. 其中 n 表示操作中 r 的最大值。
接下来 q 行中的第 i 行包含 3 个整数 ti, li, ri,表示第 i 个操作属于类型 ti,对应的参数是 li 和 ri.
Output
对于每个类型 2 的询问,输出 1 个整数表示对应的数量。
Sample Input
1 2 1 1 1 2 1 1 4 4 1 1 4 2 2 3 1 1 4 2 2 3
Sample Output
1 1 2
思路:用总线段条数减去左端点大于l和右端点小于r的线段数(这两种情况不会有重合),线段树单点更新,区间求和。
代码:
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 #define int long long 5 #define N 120000 6 int n; 7 struct BIT{ 8 int c[150000]; 9 int lowbit(int x) {return x&-x; } 10 int getsum(int x){ 11 int res=0; 12 for(int i=x;i>0;i-=lowbit(i)){ 13 res+=c[i]; 14 } 15 return res; 16 } 17 void add(int x,int y){ 18 for(int i=x;i<=n;i+=lowbit(i)){ 19 c[i]+=y; 20 } 21 } 22 }L,R; 23 signed main(){ 24 int q; 25 while(cin>>n>>q){ 26 int cnt=0;// 线段总个数 27 int A,b,c; 28 while(q--){ 29 scanf("%lld%lld%lld",&A,&b,&c); 30 if(A==1){ 31 cnt++; 32 L.add(b,1); 33 R.add(c,1); 34 }else{ 35 int ans1=cnt-R.getsum(c-1); 36 int ans2=cnt-L.getsum(b); 37 int ans=ans1-ans2; 38 printf("%lld\n",ans); 39 } 40 } 41 for(int i=0;i<=n;i++) 42 L.c[i]=0,R.c[i]=0; 43 } 44 return 0; 45 }