hud 2013腾讯编程马拉松 威威猫系列故事——晒被子

来源:互联网 发布:json封装 编辑:程序博客网 时间:2024/05/17 08:47
Problem Description
  因为马拉松初赛中吃鸡腿的题目让不少人抱憾而归,威威猫一直觉得愧对大家,这几天他悄悄搬到直角坐标系里去住了。
  生活还要继续,太阳也照常升起,今天,威威猫在第一象限晒了N条矩形的被子,被子的每条边都和坐标轴平行,不同被子的某些部分可能会叠在一起。这时候,在原点处突然发了场洪水,时间t的时候,洪水会蔓延到( t, t ),即左下角为( 0, 0 ) ,右上角为( t, t )的矩形内都有水。
  悲剧的威威猫想知道,在时间t1, t2, t3 ... tx 的时候,他有多少面积的被子是湿的?


 

Input
输入数据首先包含一个正整数T,表示有T组测试数据;
每组数据的第一行首先是一个整数N,表示有N条被子;
接下来N行,每行包含四个整数x1, y1, x2, y2,代表一条被子的左下角和右上角的坐标;
然后接下来一行输入一个整数x,表示有x次询问;
再接下来x行,输入x个严格单调递增的整数,每行一个,表示威威猫想知道的时间ti。

[Technical Specification]
T <= 5
0 < N <= 20000
1 <= x1 < x2 <= 200000
1 <= y1 < y2 <= 200000
1 <= x <= 20000
1 <= ti <= 200000 (1 <= i <= x )


 

Output
对于每次询问,请计算并输出ti时有多少面积的被子是湿的,每个输出占一行。
 


 

Sample Input
121 1 3 3 2 2 4 4512345


 

Sample Output
01588

 

解题思路:

如图所示

 

 

 

 

 

 

 

   如上:

          当矩形在对角线的某一侧时,是最简单的。假设是对角线下方。。只要让result[x1] ----- result[x2+1] 之间的值加上y2 - y1 就行了

         实现是这样的“   让matrix[x1+1] = y2 - y1;   matrix[x2+1] = y1 - y2;   (加一是因为面积在当前点才开始生效)

         (for i  =  x1 --->  x2)      gg += matrix[i]; result[i] =  result[i-1]+ gg;

         明显在i== x1+1 的时候 gg = y2 - y1  ,以后再x1 到 x2 之间的result都会加 y2 - y2 在x2 + 1处加上 y1 - y 2  ,gg == 0了

 

         当是正方形的时候,假设只有一个正方形,在x1 处  vx = 1;以后每个在 x1 到x2之间的result +=  1(vx)

           当是明显正方形每扩大一个就要增加两个单位面积   于是  设  fx += vx  这样以后每步都可以把两边多出的面积加起来了。

让result += fx * 2 + fv            但是当正方形消失了怎么办呢? 那么再建立一个数组 flag[]    在正方形消失的位置修改fv    ,这个位置fv = fv - 正方形当前的高度,

那么之后这个正方形就不影响了  因为  fx,vx  == 0了

 

 

      假设是其他情况发生,那么他们都可以被分解成上面说的矩形和正方形,  于是算法得出了。

       复杂度是 200000的 ,优化的效果不明显  就假设是o(N)的吧

 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
__int64   matrix[200009];//记录普通矩形影响
__int64   result[200009];//结果
__int64   flag  [200009];//消除已经消失的正方形影响
__int64   square[200009];//记录正方形开始点
int query[20009];//查询
void haha(int  low, int high)//处理正方形情况
{
    if(low >= high) return ;
    square[low+1] += 1;
    square[high+1] -= 1;
    flag[high+1] -= (high - low);
}
void make(int low,int high, int width)//处理普通矩形
{
    if(width <= 0) return;
    matrix[low+1] += width;
    matrix[high+1] -= width;
}
int main()
{
    int  t;
    scanf("%d",&t);
    __int64  gg = 0;
    __int64  fx = 0;
    __int64  vx = 0;
     int  x1,x2,y1,y2,  N;
     __int64 lager;
    while(t--)
    {
        memset(matrix, 0, sizeof(matrix));
        memset(flag, 0, sizeof(flag));
        memset(square, 0, sizeof(square));
        scanf("%d",&N);
        int maxM = 0;
        lager = 0;
        for(int  i = 0;i < N; i++)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            maxM = max(maxM,x2);//用于优化的,其实可以不用
            maxM = max(maxM,y2);
            if(x1 > y1)//右下角
            {
                make(x1,x2,min(x1,y2)-y1);
            }
            if(x2 > y2)//右上角
            {
                make(y2,x2,y2-max(x1,y1));
            }
            if(y1 > x1)//左下角
            {
                make(y1,y2,min(x2,y1)-x1);
            }
            if(x2 < y2)//左上角
            {
                make(x2,y2,x2-max(x1,y1));
            }
            haha(max(x1,y1),min(x2,y2));//正方形
        }
        int  q ,maxn1 = 0;
        scanf("%d",&q);
        int  f =  0;
        for(int i = 0;i < q; i++)
        {
            scanf("%d",&query[i]);
            maxn1 = max(maxn1,query[i]);//用于优化的,
        }
        for(int  i = 0;i < maxn1+10 ;i++)//枚举每个时间t下被影响的面积
        {
            if(maxM + 3 < i) break;
            gg += matrix[i];
            vx += square[i];
            fx += flag[i];
            result[i] =  result[i-1]+ gg + vx + fx*2;
            lager = max(lager,result[i]);
            fx += vx;
        }
        for(int i = 0;i < q; i++)
        {
            if(query[i] > maxM + 3) printf("%I64d\n",lager);
            else printf("%I64d\n",result[query[i]]);
        }
    }
    return 0;
}