hdu------(4302)Holedox Eating(树状数组+二分)

Holedox Eating

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3362    Accepted Submission(s): 1145

Problem Description

Holedox
is a small animal which can be considered as one point. It lives in a
straight pipe whose length is L. Holedox can only move along the pipe.
Cakes may appear anywhere in the pipe, from time to time. When Holedox
wants to eat cakes, it always goes to the nearest one and eats it. If
there are many pieces of cake in different directions Holedox can
choose, Holedox will choose one in the direction which is the direction
of its last movement. If there are no cakes present, Holedox just stays
where it is.

Input

The
input consists of several test cases. The first line of the input
contains a single integer T (1 <= T <= 10), the number of test
cases, followed by the input data for each test case.The first line of
each case contains two integers L,n(1<=L,n<=100000), representing
the length of the pipe, and the number of events.
The next n lines,
each line describes an event. 0 x(0<=x<=L, x is a integer)
represents a piece of cake appears in the x position; 1 represent
Holedox wants to eat a cake.
In each case, Holedox always starts off at the position 0.

Output

Output the total distance Holedox will move. Holedox don’t need to return to the position 0.

Sample Input

3
10 8
0 1
0 5
1
0 2
0 0
1
1
1

10 7
0 1
0 5
1
0 2
0 0
1
1

10 8
0 1
0 1
0 5
1
0 2
0 0
1
1

Sample Output

Case 1: 9
Case 2: 4
Case 3: 2

Author

BUPT

Source

2012 Multi-University Training Contest 1

代码:

  1 #include<cstring>
  2 #include<cstdio>
  3 #define maxn 100080
  4 #define inf 0x3f3f3f3f
  5 int next[maxn];
  6 int len,n;
  7 int lowbit(int x){
  8    return x&(-x);
  9 }
 10 void update(int st,int val){
 11   while(st<=len+1){
 12       next[st]+=val;
 13     st+=lowbit(st);
 14   }
 15 }
 16 int query(int st){
 17     int ans=0;
 18     while(st>0){
 19       ans+=next[st];
 20        st-=lowbit(st);
 21     }
 22   return ans;
 23 }
 24
 25 int main(){
 26   int test;
 27   int jud,tem,pos,ans;
 28   //freopen("test.in","r",stdin);
 29   //freopen("test1.in","w",stdout);s
 30   scanf("%d",&test);
 31  for(int i=1;i<=test;i++ ){
 32       scanf("%d%d",&len,&n);
 33     memset(next,0,sizeof(next));
 34        bool flag=true; //开始从0开始所以必须去右边
 35     pos=1;  //初始牛的位置在1初开始数
 36     ans=0;
 37   while(n--)
 38   {
 39      scanf("%d",&jud);
 40      if(!jud){
 41        scanf("%d",&tem);
 42        update(tem+1,1);
 43      }
 44      else{  //如果jud=1说明那条牛要吃蛋糕了
 45          //但是不知道那边有蛋糕...
 46          int left=pos, right=len+1;
 47          int mid;
 48          int rr=inf;   //记录最近的右边蛋糕位置
 49          int ll=-inf;   //记录最近的左边蛋糕位置
 50          bool iseat_r=false;
 51          int st_num=query(pos-1);  //开始位置以下的位置蛋糕的数目
 52          while(left<=right){
 53            mid=left+((right-left)>>1);
 54            if(query(mid)>st_num) {
 55              right=mid-1;
 56              rr=mid;
 57              iseat_r=true;  //表示吃到了蛋糕
 58            }
 59            else
 60              left=mid+1;
 61          }
 62          left=1;
 63          right=pos;
 64          st_num=query(pos);
 65          bool iseat_l=false;
 66         while(left<=right){
 67           mid=left+((right-left)>>1);
 68           if(st_num-query(mid-1)>0){
 69               left=mid+1;
 70             ll=mid;
 71             iseat_l=true;
 72           }
 73           else  right=mid-1;
 74         }
 75       if(iseat_l||iseat_r)  //又一边有蛋糕吃就可以了,否则什么都不做
 76       {
 77         int len1=pos-ll;
 78         int len2=rr-pos;
 79         if(len1<len2){
 80             pos=ll;
 81             ans+=len1;
 82             flag=false;
 83         }
 84         else { //如果相等,真的可以随便吃吗,以继续保持原来的方向优先
 85             if(len1>len2){
 86                 pos=rr;
 87                 ans+=len2;
 88                 flag=true;
 89             }
 90             else if(flag){ pos=rr;
 91                 ans+=len2;
 92             }
 93          else{
 94             pos=ll;
 95             ans+=len1;
 96             }
 97         }
 98            update(pos,-1);  //吃掉了一个蛋糕
 99        }
100      }
101    }
102    printf("Case %d: %d\n",i,ans);
103   }
104 return 0;
105 }

时间: 2024-11-08 21:36:27

hdu------(4302)Holedox Eating(树状数组+二分)的相关文章

HDU 2852 KiKi&#39;s K-Number (树状数组 &amp;&amp; 二分)

题意:给出对容器的总操作次数n, 接下来是这n个操作.这里对于一个容器提供三种操作, 分别是插入.删除和查找.输入0  e表示插入e.输入1  e表示删除e,若元素不存在输出No Elment!.输入2  e  k表示查找比e大且第k大的数, 若不存在则输出Not Find! 分析:这里考虑树状数组做的原因是在第三个操作的时候, 只要我们记录了元素的总数, 那通过求和操作, 便能够高效地知道到底有多少个数比现在求和的这个数要大, 例如 tot - sum(3)就能知道整个集合里面比3大的数到底有

HDU 5592 ZYB&#39;s Premutation(树状数组+二分)

题意:给一个排列的每个前缀区间的逆序对数,让还原 原序列. 思路:考虑逆序对的意思,对于k = f[i] - f[i -1],就表示在第i个位置前面有k个比当前位置大的数,那么也就是:除了i后面的数字之外,它是在剩下的数字当中第k+1大的. 知道这个之后,可以用树状数组来帮助找出剩下的数中第k大的数,刚开始我们可以让1-n中每个元素都标记为1,那么他们的前缀和就代表它是第几小.所以,我们可以对于他们的和来二分快速寻找第k大数.其实在树状数组里面是按照第(i-k)小来找的.找完之后要删除这个元素的

hdu 2852(树状数组+二分)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2852 KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2668    Accepted Submission(s): 1227 Problem Description For the k-th number,

HDU 2852 KiKi&#39;s K-Number【 树状数组 二分 】

题意:给出m个操作,0:是增加一个数,add(x,1)1:是删除一个指定的数,这个是看sum(x) - sum(x-1)是否为0,为0的话则不存在,不为0的话,则add(x,-1)2:是查询比x大的数中第k大的数,先求出比x小的个数s,假设比x大的数中第k大的数为y,那么比y小的个数有s+k个二分y的值来找 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath&g

HDU 2852 KiKi&#39;s K-Number(树状数组+二分)

KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2598    Accepted Submission(s): 1199 Problem Description For the k-th number, we all should be very familiar with it. Of course,t

HDU 1541 Stars (树状数组)

Problem Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a star be an amount of the stars that are not higher and not to the right of the given

HDU 3854 Glorious Array(树状数组)

题意:给一些结点,每个结点是黑色或白色,并有一个权值.定义两个结点之间的距离为两个结点之间结点的最小权值当两个结点异色时,否则距离为无穷大.给出两种操作,一种是将某个结点改变颜色,另一个操作是询问当前距离小于K的结点有多少对,K是一个定值. 思路:先求最初时候小于k的结点有多少对,然后每次改变颜色的时候,统计该点左侧和右侧各有多少同色和异色的结点(这一步使用树状数组),分别处理就行.另外需要预处理离某个结点最近的两个距离小于K的结点的位置. 代码写的略乱. #include<cstdio> #

HDU 3333 Turing Tree 树状数组 离线查询

题意: 给你一个数列,然后有n个查询,问你给定区间中不同数字的和是多少. 思路还是比较难想的,起码对于蒟蒻我来说. 将区间按照先右端点,后左端点从小到大排序之后,对于每个查询,我只要维护每个数字出现的最后一次就可以了(这个结论稍微想一下就可以证明是正确的). 然后就是简单的点更新,区间求和问题了- #include <cstdio> #include <cstring> #include <iostream> #include <map> #include

HDU 2689 Sort it (树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2689 Sort it Problem Description You want to processe a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. Then how many times it