看到题目本以为是扫描区域最大值,分别记录三个值,最初的想法是这样,应该也可以做只是麻烦一点。后来队友说可以看成体积并来做,把价值看成高度,神一般的思想啊。这样一想就很简单了,敲了个代码水过。。。
ACcode:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL __int64
using std::sort;
const int nsize=33333;
struct Matrix
{
int x1,x2,y1,y2,s;
}matrix[nsize];
struct Line
{
int x1,x2,y,f;
Line () {}
Line (int a,int b,int c,int d) : x1(a),x2(b),y(c),f(d){}
bool operator < (const Line &cmp) const {
return y<cmp.y;
}
}line[nsize<<1];
LL ans;
int p[5],q[5];
int X[nsize<<1];
int cov[nsize<<2];
int len[nsize<<2];
void PushUp(int rt,int l,int r)
{
if (cov[rt]) len[rt]=X[r+1]-X[l];
else if (l==r) len[rt]=0;
else len[rt]=len[rt<<1]+len[rt<<1|1];
}
void update(int rt,int l,int r,int L,int R,int v)
{
if (L<=l&&r<=R)
{
cov[rt]+=v;
PushUp(rt,l,r);
return ;
}
int m=(l+r)>>1;
if (L<=m) update(rt<<1,l,m,L,R,v);
if (R>m) update(rt<<1|1,m+1,r,L,R,v);
PushUp(rt,l,r);
}
int Fin(int key,int k)
{
int l=1,r=k;
while (l<=r)
{
int m=(l+r)>>1;
if (X[m]==key) return m;
else if (X[m]<key) l=m+1;
else r=m-1;
}
return -1;
}
int main()
{
int T,n,m,i,j,k,nx,ny,cas=0;
scanf("%d",&T);
while (T--)
{
scanf("%d %d",&n,&m);
for (i=1;i<=m;i++)
{
scanf("%d",&p[i]);
q[i]=p[i];
}
q[0]=0;
sort(q+1,q+m+1);
for (i=1;i<=n;i++)
{
scanf("%d %d %d %d %d",&matrix[i].x1,&matrix[i].y1,
&matrix[i].x2,&matrix[i].y2,&matrix[i].s);
}
for (ans=0,i=1;i<=m;i++)
{
for (nx=ny=0,j=1;j<=n;j++)
{
k=matrix[j].s;
if (p[k]>=q[i])
{
X[++nx]=matrix[j].x1;
X[++nx]=matrix[j].x2;
line[++ny]=Line(matrix[j].x1,matrix[j].x2,matrix[j].y1,1);
line[++ny]=Line(matrix[j].x1,matrix[j].x2,matrix[j].y2,-1);
}
}
memset(cov,0,sizeof(cov));
memset(len,0,sizeof(len));
sort(X+1,X+nx+1);
sort(line+1,line+ny+1);
for (k=1,j=2;j<=nx;j++)
if (X[j]!=X[j-1]) X[++k]=X[j];
for (j=1;j<ny;j++)
{
int l=Fin(line[j].x1,k);
int r=Fin(line[j].x2,k)-1;
update(1,1,k,l,r,line[j].f);
ans+=1LL*len[1]*(q[i]-q[i-1])*(line[j+1].y-line[j].y);
}
}
printf("Case %d: %I64d\n",++cas,ans);
}
return 0;
}