Hrbust 2151 变形金刚【思维+前缀和】

来源:互联网 发布:win10 占用80端口 编辑:程序博客网 时间:2024/06/04 18:21

变形金刚Time Limit: 3000 MSMemory Limit: 32768 KTotal Submit: 36(13 users)Total Accepted: 12(11 users)Rating: Special Judge: NoDescription

新一轮变形金刚来袭,这次霸天虎的头领叫做吊炸天。吊炸天有一个酷炫的攻击技能,能够横向摧毁一个矩形区域内的高楼大厦。但是有个弱点,这个矩形区域必须充满建筑物(不能有空白)。现在吊炸天面对一座城市,假设建筑物都是紧密挨着的(没有缝隙),现在按照顺序给你一些建筑物的宽和高(二维)。 这样的话...吊炸天一次性能摧毁的最大建筑面积是多少?(不考虑区域外造成的损坏)

Input 

多组测试数据:

每组数据的第一行是一个整数n,表示建筑物的数目;

接下来的n行,每行有两个整数 w,h,分别表示对应建筑物的宽和高。

(1<= T <= 50, 1 <= n <= 50000,0<=总面积<=10^9)

如果n等于0 则结束。

Output     对于每组数据,输出能一次性摧毁的最大面积。Sample Input

2

3 4

1 3

3

3 4

1 2

3 4

0

Sample Output

12

14

Source2014暑假集训练习赛(8月6日)

思路:


我们O(n)枚举一列作为起点,然后向两边贪心找最远能够和这一列组成矩形的位子。左边设定为L【i】,右边设定为R【i】.

那么我们再维护一个关于行长度的前缀和Sum【i】.那么我们维护出来的解就是Sum【R【i】】-Sum【L【i】-1】*H【i】;


那么问题就在于如何寻找L【i】和R【i】.

如果我们暴力去找的话,时间复杂度是O(n^2)很大,所以我们可以将L【i】相关信息存储成一种链式的结构,我们大致可以做到尽可能的O(1)查询。

具体实现细节参考代码即可,不难理解。


Ac代码:

#include<stdio.h>#include<iostream>#include<string.h>using namespace std;int w[50005];int h[50005];int L[50005];int R[50005];int Sum[50005];int main(){    int n;    while(~scanf("%d",&n))    {        if(n==0)break;        memset(w,0,sizeof(w));        memset(h,0,sizeof(h));        memset(L,0,sizeof(L));        memset(R,0,sizeof(R));        memset(Sum,0,sizeof(Sum));        int output=0;        for(int i=1;i<=n;i++)scanf("%d%d",&w[i],&h[i]);        for(int i=1;i<=n;i++)L[i]=R[i]=i,Sum[i]=Sum[i-1]+w[i];        for(int i=1;i<=n;i++)        {            int now=i;            while(L[now]-1>=1&&h[i]<=h[now-1])now=L[now-1];            L[i]=now;            now=i;            while(R[now]+1<=n&&h[i]<=h[now+1])now=R[now+1];            R[i]=now;            int row=Sum[R[i]]-Sum[L[i]-1];            int col=h[i];            output=max(output,row*col);        }        printf("%d\n",output);    }}