千万别用树套树 【题意:有多少线段完全覆盖某一线段【树状数组维护】】【模板题】

链接: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 }

 

上一篇:[洛谷P2661] NOIP2015 信息传递


下一篇:算法设计与分析 3.1 小火龙