hdu3255 线段树体积并

看到题目本以为是扫描区域最大值,分别记录三个值,最初的想法是这样,应该也可以做只是麻烦一点。后来队友说可以看成体积并来做,把价值看成高度,神一般的思想啊。这样一想就很简单了,敲了个代码水过。。。


ACcode:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL __int64
using std::sort;

const int nsize=33333;

struct Matrix
{
    int x1,x2,y1,y2,s;
}matrix[nsize];

struct Line
{
    int x1,x2,y,f;
    Line () {}
    Line (int a,int b,int c,int d) : x1(a),x2(b),y(c),f(d){}
    bool operator < (const Line &cmp) const {
        return y<cmp.y;
    }
}line[nsize<<1];

LL ans;
int p[5],q[5];
int X[nsize<<1];
int cov[nsize<<2];
int len[nsize<<2];


void PushUp(int rt,int l,int r)
{
    if (cov[rt]) len[rt]=X[r+1]-X[l];
    else if (l==r) len[rt]=0;
    else len[rt]=len[rt<<1]+len[rt<<1|1];
}

void update(int rt,int l,int r,int L,int R,int v)
{
    if (L<=l&&r<=R)
    {
        cov[rt]+=v;
        PushUp(rt,l,r);
        return ;
    }
    int m=(l+r)>>1;
    if (L<=m) update(rt<<1,l,m,L,R,v);
    if (R>m)  update(rt<<1|1,m+1,r,L,R,v);
    PushUp(rt,l,r);
}

int Fin(int key,int k)
{
    int l=1,r=k;
    while (l<=r)
    {
        int m=(l+r)>>1;
        if (X[m]==key) return m;
        else if (X[m]<key) l=m+1;
        else r=m-1;
    }
    return -1;
}

int main()
{
    int T,n,m,i,j,k,nx,ny,cas=0;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d %d",&n,&m);
        for (i=1;i<=m;i++)
        {
            scanf("%d",&p[i]);
            q[i]=p[i];
        }
        q[0]=0;
        sort(q+1,q+m+1);
        for (i=1;i<=n;i++)
        {
            scanf("%d %d %d %d %d",&matrix[i].x1,&matrix[i].y1,
                  &matrix[i].x2,&matrix[i].y2,&matrix[i].s);
        }
        for (ans=0,i=1;i<=m;i++)
        {
            for (nx=ny=0,j=1;j<=n;j++)
            {
                k=matrix[j].s;
                if (p[k]>=q[i])
                {
                    X[++nx]=matrix[j].x1;
                    X[++nx]=matrix[j].x2;
                    line[++ny]=Line(matrix[j].x1,matrix[j].x2,matrix[j].y1,1);
                    line[++ny]=Line(matrix[j].x1,matrix[j].x2,matrix[j].y2,-1);
                }
            }
            memset(cov,0,sizeof(cov));
            memset(len,0,sizeof(len));
            sort(X+1,X+nx+1);
            sort(line+1,line+ny+1);
            for (k=1,j=2;j<=nx;j++)
                if (X[j]!=X[j-1]) X[++k]=X[j];
            for (j=1;j<ny;j++)
            {
                int l=Fin(line[j].x1,k);
                int r=Fin(line[j].x2,k)-1;
                update(1,1,k,l,r,line[j].f);
                ans+=1LL*len[1]*(q[i]-q[i-1])*(line[j+1].y-line[j].y);
            }
        }
        printf("Case %d: %I64d\n",++cas,ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值