Family
2015-11-01 09:45
211 查看
题目
Sarila负责为今年信息组的聚会***蛋糕,她买了n个蛋糕,第i个蛋糕长度为 ai,宽度为bi,高度为1(这里长宽是可以互换的)。Sarila想组合出一个最大的长方体蛋糕塔,蛋糕塔每层的蛋糕尺寸是一样的。她决定从某一些蛋糕里切出一个x*y的子矩形,再把这些x*y的矩形蛋糕叠起来作为蛋糕塔。一块蛋糕只能切出一块x*y的子矩形,剩余部分不能继续使用,且必须沿着平行与长宽方向切割。现在她想请你帮忙,对于每一个蛋糕塔的高度h,确定x,y使得每一层蛋糕的面积尽量大。
对于100%的数据,1<=n<=3000,1<=ai,bi<=10^8
题意
即确定最大的x*y,然后满足的(a>=x)and(b>=y)的个数为h便是第h层的最大值,请你求出1到h的最大x*y分析
很明显这题允许我们用O(n2)O(n^2)的算法去做,那么我们便可以去考虑了。因为ai,bi<=10810^8,故我们可以用离散化解决ai太大的问题。
首先这题有很多种做法,我只讲我的方法,不喜勿喷,也欢迎互相讨论
我们接着分析,发现每个x,y一定时某一个ai或bj(请读者想一想)
我们先排序ai,bi,双关键字(从大到小)
那么我们便可以先枚举一个i,以ai为x。
然后我们可以把只要满足ak>=ai的bk统计一下,然后我们会发现这里是线性的(因为是从大到小,那么这个值一定也能被下一个ai+1用到,因为ai+1<=ai)
那么我们只用统计一下所有ak=ai的bk即可(这是O(n)O(n))
用桶来处理(h[i]表示bk为i的满足的个数)
我们再枚举一下j(离散的值),这时我们便知道满足:(ai<=ak)and(bi<=bk)的值,即桶里面的值。
然后用ai*bj的值去更新an[h[j],1]*an[h[j],2]的值(an[h[j],1..2]表示的是满足h[j]组数满足的最大的乘积的两个数)
代码比较丑,用了类似前缀和来处理(因为比赛没太多时间去思考。。)
用类似前缀和原因还有一个是:我是一块一块处理(相同的ai以前处理)
故用其来处理
[code]var x:array[0..10005,1..2] of longint; a:array[0..10005,1..3] of longint; i,nu,num,j,k,n:longint; an:array[0..10000,1..2] of int64; b,c,d:array[0..10000] of int64; procedure qsort(l,r:longint); var i,j,mid,mie:longint; begin i:=l;j:=r;mid:=x[(l+r)shr 1,1];mie:=x[(l+r)shr 1,2]; repeat while (x[i,1]>mid)or((x[i,1]=mid)and(x[i,2]>mie)) do inc(i); while (x[j,1]<mid)or((x[j,1]=mid)and(x[j,2]<mie)) do dec(j); if i<=j then begin x[0]:=x[i];x[i]:=x[j];x[j]:=x[0];inc(i);dec(j); end; until i>j; if l<j then qsort(l,j); if i<r then qsort(i,r); end; procedure qso(l,r:longint); var i,j,mid:longint; begin i:=l;j:=r;mid:=a[(l+r)shr 1,1]; repeat while a[i,1]<mid do inc(i); while a[j,1]>mid do dec(j); if i<=j then begin a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];inc(i);dec(j); end; until i>j; if l<j then qso(l,j); if i<r then qso(i,r); end; procedure swap(var x,y:longint); var t:longint; begin t:=x;x:=y;y:=t;end; begin assign(input,'family.in');reset(input); assign(output,'family.out');rewrite(output); readln(n); for i:=1 to n do begin readln(x[i,1],x[i,2]); if x[i,1]<x[i,2] then swap(x[i,1],x[i,2]); end; qsort(1,n); for i:=1 to n do begin inc(nu);a[nu,1]:=x[i,1];a[nu,2]:=i;a[nu,3]:=1; inc(nu);a[nu,1]:=x[i,2];a[nu,2]:=i;a[nu,3]:=2; end; qso(1,nu); a[0,1]:=0; for i:=1 to nu do begin if a[i,1]<>a[i-1,1] then begin inc(num);b[num]:=a[i,1];end; x[a[i,2],a[i,3]]:=num; end; x[0,1]:=0;i:=1; while i<=n do begin inc(d[1]);dec(d[x[i,2]+1]); for j:=i+1 to n do if x[j,1]=x[j-1,1] then begin inc(d[1]);dec(d[x[j,2]+1]);end else break; for k:=1 to num do d[k]:=d[k-1]+d[k]; for k:=1 to num do begin c[k]:=c[k]+d[k];d[k-1]:=0;end;d[num]:=0; if x[j,1]<>x[j-1,1] then dec(j); for k:=1 to num do if b[an[c[k],1]]*b[an[c[k],2]]<b[k]*b[x[i,1]] then begin an[c[k],1]:=k;an[c[k],2]:=x[i,1];end; i:=j+1; end; for i:=n downto 1 do begin for j:=i+1 to n do if b[an[i,1]]*b[an[i,2]]<b[an[j,1]]*b[an[j,2]] then an[i]:=an[j]; end; for i:=1 to n do writeln(b[an[i,1]],' ',b[an[i,2]]); close(input);close(output); end.
相关文章推荐
- NSDate的使用
- Java中Synchronized的用法
- 11_常见对象(Object类的使用)
- hdu 1431 素数回文(暴力打表,埃托色尼筛法)
- [leetcode] Nim Game
- puppet学习笔记
- Shiro使用和源码分析---1
- 从腾讯QQ升级游戏之“快速加入游戏”功能的实现缺陷看C/S之间如何正确分配相关协作
- hdu2519 新生晚会
- JavaScript——js获取url方法,方便以后页面的跳转
- 【LeetCode从零单刷】Set Matrix Zeroes
- 从腾讯QQgame高性能服务器集群架构看“分而治之”与“自治”等分布式架构设计原则
- Ubuntu 手动安装firefox以及创建快捷方式和账号同步
- CSS之Document方法的使用
- C语言中clock函数的使用
- 《山海经——五藏山经》
- 《JavaScript高级编程》学习笔记之object和array引用类型
- iOS自定义转场动画(2)——自定义Pop转场动画并加入手势驱动
- SpringMVC从Controller跳转到另一个Controller
- 从警察抓小偷看委托