HDU 3255 Farming

29 篇文章 0 订阅
6 篇文章 0 订阅

HDU 3255 Farming

线段树,扫描线

题意

二维坐标的田地,在上面按矩形区域种植。有可能一个格子种了多种作物,那么按价值最大的算。求总价值。
实际就是求立方体体积并。把作物价值想成高度。

思路

按价值离散化,一层层求。每次将价值大于当前考虑价值的边加入边表,在编表里面跑矩形面积并,乘个高度即可。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define M(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int MAXN=30007;
typedef long long LL;
struct Line
{
    int l, r;
    int h, z;
    int fl;
    Line() {}
    Line(int a, int b, int c, int d, int e) { l=a, r=b, h=c, z=d, fl=e; }
    bool operator < (const Line &l)const
    {
        return h<l.h;
    }
}line[MAXN<<1], tline[MAXN<<1];//边表与当前考虑的边表
int hax[MAXN<<1], ps[5];//hax表示x的哈希,ps表示价值
struct Stree
{
    int cov, lenth;
}stree[MAXN<<3];
void pushup(int l, int r, int rt)
{
    if(stree[rt].cov)
        stree[rt].lenth=hax[r+1]-hax[l];
    else if(l==r)
        stree[rt].lenth=0;
    else stree[rt].lenth=stree[rt<<1].lenth+stree[rt<<1|1].lenth;
}
void update(int L, int R, int c, int l, int r, int rt)
{
    if(L<=l&&r<=R)
    {
        stree[rt].cov+=c;
        pushup(l, r, rt);
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid) update(L, R, c, lson);
    if(mid<R) update(L, R, c, rson);
    pushup(l, r, rt);
}
void build(int l, int r, int rt) { M(stree, 0); }
int main()
{
    int T;scanf("%d", &T);int cas=0;
    while(T--)
    {
        int n, m;scanf("%d%d", &n, &m);
        for(int i=1;i<=m;i++)
            scanf("%d", &ps[i]);
        int lam=0;
        for(int i=1;i<=n;i++)
        {
            int a, b, c, d, e;scanf("%d%d%d%d%d", &a, &b, &c, &d, &e);
            line[++lam]=Line(a, c, b, ps[e], 1);hax[lam]=a;
            line[++lam]=Line(a, c, d, ps[e], -1);hax[lam]=c;
        }
        sort(line+1, line+1+lam);
        sort(hax+1, hax+1+lam);
        int k=unique(hax+1, hax+lam+1)-hax-2;
        ps[0]=0;sort(ps+1, ps+m+1);
        LL res=0;int cnt=0;
        for(int i=1;i<=m;i++)//按价值分层考虑
        {
            cnt=0;
            for(int j=1;j<=lam;j++)
            {
                if(line[j].z>ps[i-1])
                    tline[++cnt]=line[j];
            }
            build(1, k, 1);
            for(int j=1;j<=cnt;j++)
            {
                int l=lower_bound(hax+1, hax+k+2, tline[j].l)-hax;
                int r=lower_bound(hax+1, hax+k+2, tline[j].r)-hax-1;
                update(l, r, tline[j].fl, 1, k, 1);
                if(j!=cnt) res+=(LL)stree[1].lenth*(ps[i]-ps[i-1])*(tline[j+1].h-tline[j].h);
            }
        }
        printf("Case %d: %lld\n", ++cas, res);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值