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;
}