• 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
  • 相关阅读:
    DataTable不能通过已删除的行访问该行的信息解决方法
    datatable删除行之datatable.Rows[i].Delete()。标记之后行没有了
    js判断字符串是否在数组中
    发布webservice之后调用不通
    实体类配置xml相关属性排序问题、json前后台交互
    Java堆和栈的区别 经典总结
    Java IO
    XSL 简明教程 (下)
    XSL 简 明 教 程(上)
    跟我学XSL
  • 原文地址:https://www.cnblogs.com/hgfblog/p/4729057.html
Copyright © 2020-2023  润新知