boj_67_堆操作

来源:互联网 发布:淘宝手机端首页模版 编辑:程序博客网 时间:2024/04/27 21:15

题目描述:

   求中位数。

 

解题思路:

  用两个堆来记录中间的两位数。一个大根堆,一个小根堆。变动堆的最后一个数采用倒调整操作(这里代码可以改进成倒调序,另写一个函数效率会更高些)。变动根值采用正调整操作。本题对时间要求较严,时间复杂度不能超过nlogn。

 

代码:

#include <stdio.h>
#include <stdlib.h>
#define N 100001
#define MAX 1
#define MIN 0

double array[N];
double left_heap[N], right_heap[N];
int lcnt, rcnt;

void heap_adjust(double a[N], int cnt, int f)
{
   int l = 2*cnt, r=2*cnt+1,largest = cnt;
   double tmp;

   if( f==MAX )
   {
     if(l<=lcnt && a[l]> a[cnt])
        largest = l;
     if(r<=lcnt && a[r]> a[largest])
        largest = r;
   }
   else
   {
     if(l<=rcnt && a[l]< a[cnt])
        largest = l;
     if(r<=rcnt && a[r]< a[largest])
        largest =r;     
   }
  // printf("f=%d,largest=%d.\n",f,largest);
   if(largest != cnt)
   {
     tmp = a[largest];
     a[largest] = a[cnt];
     a[cnt] = tmp;
     heap_adjust(a, largest, f);
   }
}

main()
{
   int n, count, op, i;
   double num;
  
  while(scanf("%d",&n)!=EOF)
   {
      count = 0;
      lcnt = 0;
      rcnt = 0;
      while(n>0)
      {
         n--;
         scanf("%d",&op);
         if(1 == op)
         {
            count ++;
            scanf("%lf",&num);
            
            if(1 == count)
               left_heap[++lcnt] = num;
            else if(2 == count)
            {
               if(num >= left_heap[lcnt])
                  right_heap[++rcnt] = num;
               else
               {
                  right_heap[++rcnt] = left_heap[lcnt];
                  left_heap[lcnt] = num;
               }
            }
            else
            {
                if(num>left_heap[1]&& rcnt-lcnt < 1)//加入小根堆-右
                {
                   rcnt ++;
                   right_heap[rcnt] = num;
                   for(i=rcnt/2;i>=1;i=i/2)
                      heap_adjust(right_heap, i, MIN);
                }
                else if(num<right_heap[1]&& lcnt-rcnt <1)//加入大根堆-左
                {
                   lcnt ++;
                   left_heap[lcnt] = num;
                   for(i=lcnt/2;i>=1;i=i/2)
                      heap_adjust(left_heap, i, MAX);
                }
                else if(num>=right_heap[1]&& rcnt-lcnt == 1)//把小根堆头挪到大根堆,把num放入小根堆
                {
                   lcnt++;
                   left_heap[lcnt] = right_heap[1];
                   for(i=lcnt/2;i>=1;i=i/2)
                      heap_adjust(left_heap,i, MAX);
                   right_heap[1] = num;
                   heap_adjust(right_heap,1, MIN);
                }
                else
                {
                   rcnt++;
                   right_heap[rcnt] = left_heap[1];
                   for(i=rcnt/2;i>=1;i=i/2)
                      heap_adjust(right_heap, i, MIN);
                   left_heap[1] = num;
                   heap_adjust(left_heap, 1, MAX);
                }
            }
//            //print heap
//            printf("left heap:\n");
//            for(i=1;i<=lcnt;i++)
//               printf("%.1f\t",left_heap[i]);
//            printf("\n");
//            printf("right_heap:\n");
//            for(i=1;i<=rcnt;i++)
//               printf("%.1f\t",right_heap[i]);
//            printf("\n");

         }
         else
         {
            if( count%2 ==0 )
               printf("%.1f\n",(left_heap[1]+right_heap[1])/2);
            else
            {
               if(lcnt > rcnt)
                  printf("%.1f\n",left_heap[1]);
               else
                  printf("%.1f\n",right_heap[1]);
            }
         }
      }
   }
   system("pause");
   return 0;
}

原创粉丝点击