HDU 3642 Get The Treasury(离散化+线段树:扫描线)

HDU 3642 Get The Treasury(离散化+线段树:扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=3642

分析:

       本题要求的是重叠3次及以上的立方体体积,由于Z轴范围很小,可以枚举Z轴,然后固定了Z轴之后,就是求二维矩形的面积交>=3次的总面积了.其实Z轴就算很大也可以求,只需要把Z轴离散化即可.

比如Z轴从小到大出现了1,10,100,1000共四个值.然后假设当前考虑Z==1时,那么只需要把那些包括了[1,10]区间的立方体加入到二维矩形球面积的线段树扫描线中即可.如何判断一个立方体包括了区间[1,10]呢? 只要该立方体的Z轴最小值<=1且Z轴最大值>1,那么它就必然包括了区间[1,10].想想是不是.

       对于每个给定的Z轴区间,我们只要求出交>=3次以上的总面积res,然后用res*该Z轴区间长度,即可求出该区间的ans体积.由于X轴的范围也很大,所以X轴也需要离散化处理.

       线段树需要维护的信息有:

cover:值为0,1,2,3,4… 表示当前节点控制的X轴区被覆盖的次数.

sum: 表示当前节点控制的X轴区域被覆盖次数>=3的总长度

len1: 表示当前节点控制的X轴区域被覆盖次数=1的总长度

len2: 示当前节点控制的X轴区域被覆盖次数=2的总长度

具体实现见代码.

AC代码:1468ms

#include
#include
#include
using namespace std;
const int MAXN=2222;
#define lson i*2,l,m
#define rson i*2+1,m+1,r
int cover[MAXN*4],sum[MAXN*4],len1[MAXN*4],len2[MAXN*4];
int X[MAXN],Z[MAXN];
int cnt_x,cnt_z;
struct seg
{
    int l,r,h,d;
    seg(){}
    seg(int a,int b,int c,int d):l(a),r(b),h(c),d(d){}
    bool operator < (const seg& b)const
    {
        return h=3)
    {
        sum[i]=X[r+1]-X[l];
        len1[i]=len2[i]=0;
    }
    else if(cover[i]==2)
    {
        sum[i]=sum[i*2]+sum[i*2+1]+len1[i*2]+len1[i*2+1]+len2[i*2]+len2[i*2+1];
        len2[i]=X[r+1]-X[l]-sum[i];
        len1[i]=0;
    }
    else if(cover[i]==1)
    {
        sum[i]=sum[i*2]+sum[i*2+1]+len2[i*2]+len2[i*2+1];
        len2[i]=len1[i*2]+len1[i*2+1];
        len1[i]=X[r+1]-X[l]-sum[i]-len2[i];
    }
    else
    {
        sum[i]=sum[i*2]+sum[i*2+1];
        len1[i]=len1[i*2]+len1[i*2+1];
        len2[i]=len2[i*2]+len2[i*2+1];
    }
}
void update(int ql,int qr,int v,int i,int l,int r)
{
    if(ql<=l&&r<=qr)
    {
        cover[i]+=v;
        PushUp(i,l,r);
        return ;
    }
    int m=(l+r)>>1;
    if(ql<=m) update(ql,qr,v,lson);
    if(mZ[i])
                {
                    ss[cnt++]=seg(cubes[j].a.x,cubes[j].b.x,cubes[j].a.y,1);
                    ss[cnt++]=seg(cubes[j].a.x,cubes[j].b.x,cubes[j].b.y,-1);
                }
            }
            sort(ss,ss+cnt);
            memset(cover,0,sizeof(cover));
            memset(sum,0,sizeof(sum));
            memset(len1,0,sizeof(len1));
            memset(len2,0,sizeof(len2));
            for(int j=0;j


你可能感兴趣的:(ACM--题解汇总,注意!,have,a,question,★★★)