把价值p看做这个矩形上的高也就是长方体了。然后解法与线段树求矩形并差不多,就是多了一个枚举高度的循环。
#include<stdio.h>
#define maxn 30010
#include<string.h>
#include<algorithm>
using namespace std;
typedef struct
{
int l,r,y,s,h,tag;
}Seg;
Seg ss[4*maxn]; int sum[10*maxn],cnt[10*maxn]; int p[10]; int X[4*maxn];
int cmp( Seg a,Seg b)
{
return a.y<b.y;
}
int Bin(int key ,int n)
{
int l=1,r=n; int m;
while( l<= r)
{
m=(l+r)/2;
if( X[m]==key ) return m;
if( X[m] < key ) l=m+1;
else r=m-1;
}
return -1;
}
void update(int a,int b,int c,int l,int r,int rt)
{
if( l==a && r==b )
{
cnt[rt]+=c;
if( cnt[rt] ) sum[rt]=X[r+1]-X[l];
else
if( l==r ) sum[rt]=0;
else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
return;
}
int m=(l+r)/2;
if( b<=m ) update(a,b,c,l,m,rt<<1);
else if( a>m ) update(a,b,c,m+1,r,rt<<1|1);
else
{
update(a,m,c,l,m,rt<<1);
update(m+1,b,c,m+1,r,rt<<1|1);
}
if( cnt[rt] ) sum[rt]=X[r+1]-X[l];
else
if( l==r) sum[rt]=0;
else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int main()
{
int T,i,j,k,m,n,a,b,c,d,s,cas=1;
scanf("%d",&T);
while(T--)
{
k=1; long long ans=0;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++) scanf("%d",p+i);
for(i=1;i<=n;i++)
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&s);
ss[k].l=a; ss[k].r=c; ss[k].y=b; ss[k].s=1; ss[k].h=p[s];
X[k]=a; ss[k].tag=1;
k++;
ss[k].l=a; ss[k].r=c; ss[k].y=d; ss[k].s=-1; ss[k].h=p[s];
X[k]=c; ss[k].tag=1;
k++;
}
sort(X+1,X+k);
sort(ss+1,ss+k,cmp);
sort(p+1,p+m+1);
p[0]=0;
int xlen=2;
for(i=2;i<k;i++)
if( X[i]!=X[i-1] ) X[xlen++]=X[i];
for(i=0;i<m;i++)
{
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
for( j=1;j<k;j++ )
if( ss[j].h <= p[i] ) ss[j].tag=0;
for(j=1;j<k;j++)
{
if( ss[j].tag==0 ) continue;
int l= Bin(ss[j].l , xlen-1);
int r= Bin(ss[j].r, xlen-1 )-1;
if( l<=r ) update(l,r,ss[j].s,1,xlen-1,1);
int jj=j+1;
while( ss[jj].tag==0 && jj<k)
{
jj++;
}
if( jj<k ) ans+=((long long)sum[1])*(ss[jj].y-ss[j].y)*(p[i+1]-p[i]);
}
}
printf("Case %d: %I64d\n",cas++,ans);
}
return 0;
}