题意 :略
首先我们先假设出a1,b1和a2,b2分别为(1,2),和(2,2)。那么我们发现,其实(1,2)对于答案是根本没有贡献的。
所以对于b相同的,取a最大的即可。
首先我们定义一个矩阵Map[N][N],Map[c'][d']代表当c=c',d=d'的时候,a所能取到的最大值。
那么对于一个点c',d'假如任何的(c''>=c'&&d''>=d'(不包括点(c',d'))如果都没有Map[c''][d'']都小于Map[c'][d'],则这个点是对答案有贡献的。
因为相同的点可能不止一个,所以我们可以开一个辅助矩阵来存储
我们可以用二维线段树来进行查询。
这个问题便解决了
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define llson j<<1,l,mid
#define rrson j<<1|1,mid+1,r
#define maxn 1010
typedef long long ll;
using namespace std;
ll Map[maxn][maxn],Max[maxn*4][maxn*4];
ll fange[maxn][maxn];
ll n,q,t,ans;
void pushup(ll i,ll j)
{
Max[i][j]=max(Max[i][j<<1],Max[i][j<<1|1]);
}
void build_y(ll i,ll u,ll j,ll l,ll r)
{
if(l==r)
{
Max[i][j]=Map[u][l];
return ;
}
ll mid=(l+r)>>1;
build_y(i,u,llson);build_y(i,u,rrson);
pushup(i,j);
}
void build_x(ll i,ll l,ll r)
{
if(l==r)
{
build_y(i,l,1,1,n);
return ;
}
ll mid=(l+r)>>1;
build_x(lson);build_x(rson);
}
ll query_y(ll i,ll j,ll l,ll r,ll y1,ll y2)
{
if(l==y1&&y2==r) return Max[i][j];
ll mid=(l+r)>>1;
if(y2<=mid) return query_y(i,llson,y1,y2);
else if(y1>mid) return query_y(i,rrson,y1,y2);
else return max(query_y(i,llson,y1,mid),query_y(i,rrson,mid+1,y2));
}
void query_x(ll i,ll l,ll r,ll x1,ll x2,ll y1,ll y2)
{
if(l==r)
{
ans=max(ans,query_y(i,1,1,n,y1,y2));
return ;
}
ll mid=(l+r)>>1;
if(x1<=mid) query_x(lson,x1,x2,y1,y2);
if(x2>mid) query_x(rson,x1,x2,y1,y2);
}
struct NODE
{
ll x,y,val;
}a[100010],b[100010];
bool cmp(NODE a,NODE b)
{
return a.val<b.val;
}
int main()
{
ll T;
ll n1,m1,i,j,i1=1;
// freopen("in.txt","r",stdin);
scanf("%lld",&T);
n=1000;
while(T--)
{
memset(Map,0,sizeof(Map));
memset(fange,0,sizeof(fange));
scanf("%lld%lld",&n1,&m1);
for(i=1;i<=n1;i++)
scanf("%lld%lld",&a[i].x,&a[i].val);
for(i=1;i<=m1;i++)
scanf("%lld%lld%lld",&b[i].x,&b[i].y,&b[i].val);
sort(a+1,a+1+n1,cmp);
sort(b+1,b+1+m1,cmp);
i=1;j=1;
ll tmp=0;
ll time=1;
for(i=1;i<=n1;i++)
{
tmp=a[i].x;time=1;
while(i+1<=n1&&a[i].val==a[i+1].val)
{
if(tmp<a[i+1].x)
{
tmp=a[i+1].x;
time=1;
}
else if(tmp==a[i+1].x)
{
time++;
}
i++;
}
while(j<=m1&&b[j].val<=a[i].val)
{
if(b[j].val==a[i].val)
{
if(Map[b[j].x][b[j].y]<tmp)
{
Map[b[j].x][b[j].y]=tmp;
fange[b[j].x][b[j].y]=time;
}
else if(Map[b[j].x][b[j].y]==tmp)
{
fange[b[j].x][b[j].y]+=time;
}
}
j++;
}
}
ll answer=0;
build_x(1,1,n);
for(i=1;i<=1000;i++)
for(j=1;j<=1000;j++)
{
if(i==1000&&j==1000)
{
answer+=fange[i][j];
continue;
}
else if(i==1000)
{
if(fange[i][j])
{
ans=0;
query_x(1,1,n,i,n,j+1,n);
if(ans<Map[i][j])
answer+=fange[i][j];
}
}
else if(j==1000)
{
if(fange[i][j])
{
ans=0;
query_x(1,1,n,i+1,n,j,n);
if(ans<Map[i][j])
answer+=fange[i][j];
}
}
else if(fange[i][j])
{
ans=0;
query_x(1,1,n,i+1,n,j,n);
if(ans<Map[i][j])
{
ans=0;
query_x(1,1,n,i,n,j+1,n);
if(ans<Map[i][j])
{
answer+=fange[i][j];
}
}
}
}
printf("Case #%lld: ",i1++);
printf("%lld\n",answer);
}
return 0;
}