HDU3255(线段树+扫描线)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3255

 

题意:在一块地上种蔬菜,对于同一块地蔬菜价值高的一定是最后存活,求最后的蔬菜总值,也就是不同的矩形覆盖,有的矩

形肯定在最上面。

 

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>

using namespace std;
const int N = 160005;

#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1

int cnt[N],M,v[N];
double D[N],sum[N];

struct Line
{
    double l,r,h;
    int s,v;
    Line(){}
    Line(double a,double b,double c,int d,int e):l(a),r(b),h(c),s(d),v(e){}
    bool operator< (const Line &cmp)const
    {
        return h<cmp.h;
    }
}L[N],temp[N];

int BinarySearch(double x)
{
    int l,r,m;
    l=1;r=M;
    while(l<=r)
    {
        m=(l+r)>>1;
        if(D[m]==x)
        return m;
        if(D[m]<x) l=m+1;
        else  r=m-1;
    }
}

void Pushup(int l,int r,int rt)
{
    if(cnt[rt]) sum[rt] = D[r+1] - D[l];
    else if(l==r) sum[rt]=0;
    else  sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

void Update(int x,int y,int z,int l,int r,int rt)
{
    if(x<=l&&r<=y)
    {
        cnt[rt]+=z;
        Pushup(l,r,rt);
        return ;
    }
    int mid=(l+r)>>1;
    if(x<=mid)
       Update(x,y,z,lson);
    if(y>mid)
       Update(x,y,z,rson);
    Pushup(l,r,rt);
}

int main()
{
    int n,i,j,k,ca=1,l,r,m,ct,t;
    double ans,lx,ly,rx,ry;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        k=0;
        for(i=1;i<=m;i++)
        scanf("%d",&v[i]);
        for(i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf%d",&lx,&ly,&rx,&ry,&r);
            D[++k]=lx;
            L[k]=Line(lx,rx,ly,1,v[r]);
            D[++k]=rx;
            L[k]=Line(lx,rx,ry,-1,v[r]);
        }
        sort(D+1,D+1+k);
        sort(L+1,L+1+k);
        M=1;
        for(i=2;i<=k;i++)
        if(D[i]!=D[i-1])
        D[++M]=D[i];
        ans=0;
        v[0]=0;
        sort(v,v+m+1);
        for(j=1;j<=m;j++)
        {
            ct=0;
            for(i=1;i<=k;i++)
                if(L[i].v>v[j-1])
                    temp[ct++]=L[i];
            memset(cnt,0,sizeof(cnt));
            memset(sum,0,sizeof(sum));
            for(i=0;i<ct-1;i++)
            {
                l=BinarySearch(temp[i].l);
                r=BinarySearch(temp[i].r)-1;
                if(l<=r)
                Update(l,r,temp[i].s,1,M,1);
                ans+=sum[1]*(double)(v[j]-v[j-1])*(temp[i+1].h-temp[i].h);
            }
        }
        printf("Case %d: %.0lf\n",ca++,ans);
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值