2012 ACM/ICPC Asia Regional Hangzhou Online HDOJ 4417 Super Mario

来源:互联网 发布:看电影用什么软件 编辑:程序博客网 时间:2024/06/06 08:43

2012ACM ICPC杭州赛区网络赛

比赛的时候线段树死搞,害得我五个小时毫无收获,下来后发誓要做出来。搜了下,线段树貌似可以ac,单大多数说划分树,然后直接百度,看了一下,有些收获,分享一下自己的感受和大家分享一下吧。

划分树:

 谈谈我对划分树的理解:实际上划分树是以线段树的形式模拟和记录快速排序的过程;

                                            如何模拟:(回想快速排序:A数组分成两部分B,C,小于等于某个数x的放x的左边数组B,其余的放右边数组C,然后对B跟C做相同的操作),只不过划分树划分到左右两部分的时候要保证B数组的所有数与A数组中数的前后顺序一样,C数组也一样。

                                                               例如A(0 5 6 2 8)按x=5划分成B(0 2 5),C(6 8),B C数组中数的顺序固定,不能随意,后面会说明为什么要这样。

                                           如何记录:(回想线段树:1->n 的下一层1->(1+n)/2和(1+n)/2+1->n,刚好和上面划分规则差不多)可以想象对于n的数组最多log[n]层

                                      所用到的数据结构就一个结构体node{

                                                                                                       array[Max] ;//记录这一层排成啥样了

                                                                                                        num[Max];//num[i]记录前i个数有多少个进了左边数组

                                                                                                       }

                                                                                                     

                                      有了这些后那么求区间【a,b】中小于等于c的数的个数了===【1,b】-【1,a-1】中c的个数;

                                      求【1,b】中的个数,直接进入第一层,如果划分的数为x;

                                     两种情况:(至于等于,就细节处理吧)

                                                      1,c比x小,那么直接进左边数组找;        num【b】中记录了【1,b】进入左边数组的个数,而且是在左边数组中靠左排列的,这就是上面为什么要按顺序排列的原因了;

                                                     2,c比x大,那么进入左边的个数就出来了,进入右边的数也同样在右边数组靠左排列递归求出;

                               至此为止算法基本讲完了,比赛的拿到题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4417

我的代码:

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define Max 100001
int array[Max],sorted[Max];
struct N
{
 int array[Max];
 int num[Max];
}node[101];
int n,m;
int cmp(const void *a,const void *b)
{
 return *(int *)a-*(int *)b;
}
int build(int l,int r,int pre)
{
 if(l==r)
  return 0;
 int i,mid=(l+r)/2,lnextl=l,rnextl=mid+1,minnum=0,temp;
 memset(node[pre].num+l,0,sizeof(int)*(r-l+1));
 for(i=l;i<=r;i++)
 {
  if(node[pre].array[i]<sorted[mid])
  {
   minnum++;
  }
 }
 temp=mid-l+1-minnum;
 for(i=l;i<=r;i++)
 {
  if(node[pre].array[i]<sorted[mid])
  {
   node[pre+1].array[lnextl++]=node[pre].array[i];
   node[pre].num[i]++;
  }
  else if(node[pre].array[i]==sorted[mid]&&temp>0)
  {
   node[pre+1].array[lnextl++]=sorted[mid];
   node[pre].num[i]++;
   temp--;
  }
 }
 for(i=l;i<=r;i++)
 {
  if(node[pre].array[i]>=sorted[mid])
  {
   if(!node[pre].num[i])
   {
    node[pre+1].array[rnextl++]=node[pre].array[i];
   }
  }
 }
 for(i=l+1;i<=r;i++)
  node[pre].num[i]+=node[pre].num[i-1];
 build(l,mid,pre+1);
 build(mid+1,r,pre+1);
 return 0;
}
int serch(int l,int r,int w,int pre,int prel,int prer)
{
 if(r<l)
  return 0;
 if(prel==prer)
 {
  return node[pre].array[prel]<=w;
 }
 int mid=(prel+prer)/2;
 if(w>=sorted[mid])
 {
  return node[pre].num[r]+serch(mid+1,mid+(r-l+1)-node[pre].num[r],w,pre+1,mid+1,prer);
 }
 else
 {
  return serch(l,l+node[pre].num[r]-1,w,pre+1,prel,mid);
 }
 return 0;
}
int main()
{
 int i,cases,a,b,c,ca=0;
 scanf("%d",&cases);
 while(cases--)
 {
  scanf("%d%d",&n,&m);
  for(i=1;i<=n;i++)
  {
   scanf("%d",&array[i]);
  }
  memcpy(sorted+1,array+1,sizeof(int)*n);
  memcpy(node[1].array+1,array+1,sizeof(int)*n);
  qsort(sorted+1,n,sizeof(int),cmp);
  build(1,n,1);
  printf("Case %d:\n",++ca);
  for(i=1;i<=m;i++)
  {
   scanf("%d%d%d",&a,&b,&c);
   printf("%d\n",serch(1,b+1,c,1,1,n)-serch(1,a,c,1,1,n));
  }
 }
 return 0;
}

欢迎大家做评论,各种意见砸过来!

原创粉丝点击