基本思想就是:增加一个维度h表示价值,问题转换为求n个重叠长方体的体积。按h从下往上,排除高度不够的长方体,扫描一遍得到当前平面的面积 再乘以 当前层和前一层的高度差。所有体积累加就是答案了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N=60005;
typedef long long LL;
struct node{
int x,y1,y2;
int f,h;
}line[N],tline[N];
int y[N],h[5];
int wide[N*4],num[N*4];
int cmp(node a,node b){
return a.x<b.x;
}
void build(int l,int r,int rt){
wide[rt]=0;
num[rt]=0;
if(l==r)
return;
int m=(l+r)/2;
build(lson);
build(rson);
}
void push_up(int l,int r,int rt){
if(num[rt])
wide[rt]=y[r+1]-y[l];
else if(l==r)
wide[rt]=0;
else
wide[rt]=wide[rt*2]+wide[rt*2+1];
}
void update(int a,int b,int c,int l,int r,int rt){//线段更新
if(a<=l&&b>=r){
num[rt]+=c;
push_up(l,r,rt);
return;
}
int m=(l+r)/2;
if(a<=m)
update(a,b,c,lson);
if(b>m)
update(a,b,c,rson);
push_up(l,r,rt);
}
void addLine(int x,int y1,int y2,int f,int h,int cnt){
line[cnt].x=x;
line[cnt].y1=y1;
line[cnt].y2=y2;
line[cnt].f=f;
line[cnt].h=h;
}
int main(){
int n,m,tt,t=1;
int x1,x2,y1,y2,p;
for(cin>>tt;t<=tt;t++){
cin>>n>>m;
for(int i=1;i<=m;i++)
scanf("%d",&h[i]);
int cnt=0;
for(int i=0;i<n;i++){
scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&p);
addLine(x1,y1,y2,1,h[p],cnt);
y[cnt++]=y1;
addLine(x2,y1,y2,-1,h[p],cnt);
y[cnt++]=y2;
}
h[0]=0;
sort(h,h+m+1);//--放前面是错的
sort(y,y+cnt);
int nn=unique(y,y+cnt)-y;
sort(line,line+cnt,cmp);
LL ans=0;
for(int k=0;k<m;k++){//按高度扫描
build(0,nn-1,1);
int tcnt=0;
for(int i=0;i<cnt;i++)//排除高度不够的
if(line[i].h>h[k])
tline[tcnt++]=line[i];
for(int i=0;i<tcnt-1;i++){
int left=lower_bound(y,y+nn,tline[i].y1)-y;
int right=lower_bound(y,y+nn,tline[i].y2)-y-1;//线段要-1
update(left,right,tline[i].f,0,nn-1,1);
ans+=(LL)wide[1]*(tline[i+1].x-tline[i].x)*(h[k+1]-h[k]);
}
}
printf("Case %d: %I64d\n",t,ans);
}
return 0;
}