纠结了几个小时,不过还是很值得的,学到了不少东西
将蔬菜价值看做高的话就将题目转换为求立方体交的体积
先试想下若每种蔬菜的价值是一样即所有立方体的高度都一样的情况下,求其体积其实就是先求面积的交,再乘上高就是了
但是高度不尽相同怎么办呢?题目给出的高度最多就三种,于是可以枚举高度分层级求体积,最后将不同层级的体积累加便是答案
求面积交的时候我习惯的modify+query方法在这里会超时,在别人那里学到了一种更优秀的方法,一次修改向上更新y坐标差值
需要注意更新的策略:某一区间有覆盖的标记,那么该区间的dy就是该区间的长度不管儿子,否则不能直接令dy=0,而必须从儿子节点获取dy,此策略不管在更新cover或是向上更新时都应如此
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<iostream>
using namespace std;
#define MAXN 60005
#define lch p<<1
#define rch p<<1|1
#define mid (t[p].l+t[p].r)>>1
#define ll long long
struct node
{
int l,r;
ll dy;
int cover;
}t[MAXN<<2];
struct segment
{
ll x,yd,yu;
ll h;
int lr;
segment(){}
segment(ll x,ll yd,ll yu,ll h,int lr):x(x),yd(yd),yu(yu),h(h),lr(lr){}
bool operator < (const segment &a) const
{
return x<a.x;
}
}seg[MAXN],tseg[MAXN];
ll yy[MAXN];
void construct(int l,int r,int p)
{
t[p].l=l,t[p].r=r;
t[p].cover=t[p].dy=0;
if(l+1>=r) return ;
ll m=mid;
construct(l,m,lch);
construct(m,r,rch);
}
void pushup(int p)
{
if(t[p].cover) t[p].dy=yy[t[p].r]-yy[t[p].l];
else if(t[p].l+1==t[p].r) t[p].dy=0;
else t[p].dy=t[lch].dy+t[rch].dy;
}
void modify(int l,int r,int op,int p)
{
if(t[p].l>=l&&t[p].r<=r)
{
t[p].cover+=op;
pushup(p);
return ;
}
if(t[p].l+1==t[p].r) return ;
int m=mid;
if(l<=m) modify(l,r,op,lch);
if(r>=m) modify(l,r,op,rch);
pushup(p);
}
map<ll,int> rec;
int h[10];
int main()
{
int cas,n,m;
ll x1,y1,x2,y2;
int valid;
scanf("%d",&cas);
for(int kcas=1;kcas<=cas;kcas++)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d",&h[i]);
int i=0;
for(i=0;i<(n<<1);i+=2)
{
scanf("%I64d%I64d%I64d%I64d%d",&x1,&y1,&x2,&y2,&valid);
seg[i]=segment(x1,y1,y2,h[valid],1);
seg[i+1]=segment(x2,y1,y2,h[valid],-1);
yy[i]=y1;
yy[i+1]=y2;
}
sort(seg,seg+i);
sort(yy,yy+i);
sort(h+1,h+1+m);
int up=unique(yy,yy+i)-yy;
rec.clear();
for(i=0;i<up;i++)
rec[yy[i]]=(ll)i;
ll ans=0;
for(i=1;i<=m;i++)
{
ll area=0;
int tn=0;
construct(0,up-1,1);
for(int j=0;j<(n<<1);j++)
if(seg[j].h>h[i-1])
tseg[tn++]=seg[j];
for(int j=0;j<tn-1;j++)
{
modify(rec[tseg[j].yd],rec[tseg[j].yu],tseg[j].lr,1);
area+=(tseg[j+1].x-tseg[j].x)*t[1].dy;
}
ans+=area*(ll)(h[i]-h[i-1]);
}
printf("Case %d: %I64d\n",kcas,ans);
}
return 0;
}