HDU 5372 Segment Game(离散化+树状数组)

 
 
Problem Description
 
Lillian is a clever girl so that she has lots of fans and often receives gifts from her fans.

One day Lillian gets some segments from her fans Lawson with lengths of 1, 2, 3 ... and she
intends to display them by adding them to a number line.At the i-th add operation, she will
put the segment with length of i on the number line.Every time she put the segment on the
line, she will count how many entire segments on that segment. During the operation, she
may delete some segments on the line.(Segments are mutually independent)
 
Input
 
There are multiple test cases.

The first line of each case contains a integer n — the number of operations
(1<=n<=2105,n<=7105)

Next n lines contain the descriptions of the operatons,one operation per line.Each operation
contains two integers a , b. 

if a is 0,it means add operation that Lilian put a segment on the position b(|b|<109) of the line.
(For the i-th add operation, she will put the segment on [b, b+i] of the line, with length of i.)

if a is 1, it means delete operation that Lilian will delete the segment which was added at the
b-th add operation.
 
Output
 
For i-th case,the first line output the test case number.

Then for each add operation,ouput how many entire segments on the segment which Lillian
newly adds.
 
Sample Input
 
3
0 0
0 3
0 1
5
0 1
0 0
1 1
0 1
0 0
 
Sample Output
 
Case #1:
0
0
0
Case #2:
0
1
0
2
 
Hint
 
For the second case in the sample:
 
At the first add operation, Lillian adds a segment [1, 2] on the line.
 
At the second add operation, Lillian adds a segment [0, 2] on the line.
 
At the delete operation, Lillian deletes a segment which added at the first add operation.
 
At the third add operation, Lillian adds a segment [1, 4] on the line.
 
At the fourth add operation, Lillian adds a segment [0, 4] on the line
 
 
题意:有两种操作方法,输入a b。
① a==0,插入线段[b,b+i](i表示第i次进行插入操作)
② a==1,删除插入的第b条线段。
给你n个操作,问每次进行插入操作时,被当前线段完全覆盖的线段的条数。
 
题解:因为线段长度是递增的,不会出现后面的线段被前面的线段完全覆盖,所以对于新插入的线
段,查询有多少个线段左端点大于等于该线段的左端点。再查询有多少个线段的右端点大于该线
右端点, 两者之差就是答案。用两个树状数组搞定。
 
由于坐标范围很大,需要离散。
 
 
 
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 const int MAXN = 200005;
 7 //数组c分别存储大于等于左端点和大于右端点的线段数
 8 int c[2*MAXN][2];
 9 int op[MAXN], L[MAXN], id[MAXN], pos[2*MAXN];
10 int lowbit(int x)
11 {
12     return x&(-x);
13 }
14 int getSum(int n, int num)
15 {
16     int sum = 0;
17     while (n > 0){
18         sum += c[n][num];
19         n -= lowbit(n);
20     }
21     return sum;
22 }
23 void change(int n, int val, int num, int ans)
24 {
25     while (n <= ans){
26         c[n][num] += val;
27         n += lowbit(n);
28     }
29 }
30 int main()
31 {
32     int n, cnt = 0;
33     while (~scanf("%d", &n)){
34         int ans = 0, num = 1;
35         for (int i=1; i<=n; i++){
36             scanf("%d %d", &op[i], &L[i]);
37             if (op[i] == 0){
38                 pos[++ans] = L[i];
39                 pos[++ans] = L[i] + num;
40                 id[num++] = i;
41             }
42         }
43         //先排序,再离散化,利用去重函数使得每个坐标有一个唯一的标识
44         sort(pos+1, pos+ans+1);
45         ans = unique(pos+1, pos+ans+1) - pos - 1;
46         num = 1;
47         memset(c, 0, sizeof(c));
48         ++cnt;
49         printf("Case #%d:
", cnt);
50         for (int i=1; i<=n; i++){
51             if (op[i] == 0){
52                 int x = lower_bound(pos+1, pos+ans+1, L[i]) - pos;
53                 int y = lower_bound(pos+1, pos+ans+1, L[i]+num) - pos;
54                 int ans1 = getSum(ans, 0) - getSum(x-1, 0);
55                 int ans2 = getSum(ans, 1) - getSum(y, 1);
56                 num++;
57                 printf("%d
", ans1-ans2);
58                 change(x, 1, 0, ans);
59                 change(y, 1, 1, ans);
60             }
61             else{
62                 int x = lower_bound(pos+1, pos+ans+1, L[id[L[i]]]) - pos;
63                 int y = lower_bound(pos+1, pos+ans+1, L[id[L[i]]]+L[i]) - pos;
64                 change(x, -1, 0, ans);
65                 change(y, -1, 1, ans);
66             }
67         }
68     }
69     return 0;
70 }
View Code
原文地址:https://www.cnblogs.com/hgfblog/p/4729057.html