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;
}
欢迎大家做评论,各种意见砸过来!
- 2012 ACM/ICPC Asia Regional Hangzhou Online HDOJ 4417 Super Mario
- Super Mario&&2012 ACM/ICPC Asia Regional Hangzhou Online
- 2012 ACM/ICPC Asia Regional Hangzhou Online ,HDU4417-Super Mario
- 2013 ACM/ICPC Asia Regional Hangzhou Online
- HDU4417-树状数组2012 ACM/ICPC Asia Regional Hangzhou Online
- 2013 ACM/ICPC Asia Regional Hangzhou Online 个人总结
- 2013 ACM/ICPC Asia Regional Hangzhou Online ----Two Rabbits
- 2013 ACM/ICPC Asia Regional Hangzhou Online 1008 Two Rabbits
- 2012 ACM/ICPC Asia Regional Changchun Online
- 2012 ACM/ICPC Asia Regional Tianjin Online
- 2012 ACM/ICPC Asia Regional Jinhua Online
- The 37th ACM/ICPC Asia Regional HangZhou Site Online Contest - F
- hdu 4740 The Donkey of Gui Zhou 深搜(2013 ACM/ICPC Asia Regional Hangzhou Online 1003)
- HDU 4739 Zhuge Liang's Mines (2013 ACM/ICPC Asia Regional Hangzhou Online)
- 2013 ACM/ICPC Asia Regional Hangzhou Online(解题报告) 正在更新
- HDU4747 2013 ACM/ICPC Asia Regional Hangzhou Online Mex(线段树)
- HDU 4741 Save Labman No.004 2013 ACM/ICPC Asia Regional Hangzhou Online
- 2012 ACM/ICPC Asia Regional Changchun Online HDOJ 4272 连连看
- linux kernel 串口设置属性
- asmck
- 两个数之间的最短路径问题
- vi使用方法
- Java 笔记 1
- 2012 ACM/ICPC Asia Regional Hangzhou Online HDOJ 4417 Super Mario
- 根据集合动态生成多个多选框并这设置其id的值
- uclibc和glibc的差别
- ADF11g-015:ADF中af:forEach和af:iterator标签的区别
- 基于TMS320DM642视频采集驱动开发
- ActiveX(六)
- javascript 浏览器兼容性心得
- 移动游戏开发引擎
- java对象内存占用情况分析