题意有一点点绕…但最终就是找三维坐标内满足没有点的三个坐标都大于此点的点的数量。
首先先按输入的b,e分组。然后枚举不同的b,一个小trick就是同组中,将c,d放到二维坐标中必然右上角是没点的时候,这个点才能通过选本组中最大的a来使得满足条件。
这些点可以通过bit来check,注意c,d相同的点要放在一起check。
用pair数组
d
[
c
]
[
d
]
d[c][d]
d[c][d]来表示最大的a,和数量。
不同的组中,相同的c,d应该取最大的a。
最后搞完之后,就枚举c,d来累计答案。但是还有一些点是可能不合法的,就是存在
c
′
>
c
∣
∣
d
′
>
d
&
&
d
[
c
′
]
[
d
′
]
.
a
>
d
[
c
]
[
d
]
.
a
c'>c|| d'>d~~ \&\& ~~d[c'][d'].a>d[c][d].a
c′>c∣∣d′>d && d[c′][d′].a>d[c][d].a的情况时,c,d是不能合法的。这时候搞一个数组记录一下后缀的最大值即可。
大致思路就是这样,有一些细节见代码:
#include <bits/stdc++.h>
using namespace std;
const int N =1e5+3;
#define pb push_back
#define fi first
#define se second
#define LL long long
int t,cas,n,m;
pair<int,LL>d[1003][1003];
int mx[1003][1003];
vector<int>v[N];
vector<pair<int,int>>g[N];
int tr[1003];
void add(int x,int y){
for(;x;x-=x&-x)tr[x]+=y;
}
int get(int x){
int y=0;
for(;x<=1000;x+=x&-x)y+=tr[x];
return y;
}
int main(){
for(scanf("%d",&t),cas=1;cas<=t;cas++){
scanf("%d%d",&n,&m);
for(int i=1;i<=100000;i++)v[i].clear(),g[i].clear();
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
d[i][j]={0,0};
}
}
for(int i=1;i<=n;i++){
int l,r;
scanf("%d%d",&l,&r);
v[r].pb(l);
}
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
g[z].pb({x,y});
}
for(int i=1;i<=100000;i++){
sort(v[i].begin(),v[i].end(),[](int x,int y){return x>y;});
sort(g[i].begin(),g[i].end(),[](pair<int,int> x,pair<int,int> y){
if(x.fi==y.fi)return x.se>y.se;
return x.fi>y.fi;
});
int l=v[i].size(),r=g[i].size();
if(!l ||!r)continue;
int cnt=0,mx=v[i][0];
for(auto k:v[i]){
if(k==v[i][0])++cnt;
}
int inx=0;
for(int j;inx<r;inx=j+1){
j=inx;
while(j+1<r&&g[i][j+1].fi==g[i][j].fi&&g[i][j+1].se==g[i][j].se)j++;
for(int k=inx;k<=j;k++){
auto x=g[i][k];
if(!get(x.se)){
if(d[x.fi][x.se].fi<mx){
d[x.fi][x.se]={mx,cnt};
}else if(d[x.fi][x.se].fi==mx){
d[x.fi][x.se].se+=cnt;
}
}
}
for(int k=inx;k<=j;k++)add(g[i][k].se,1);
}
for(int j=0;j<r;j++){
int x=g[i][j].se,y=g[i][j].fi;
add(x,-1);
}
}
LL ans=0;
for(int i=1000;i>=1;i--){
for(int j=1000;j>=1;j--){
mx[i][j]=max({mx[i+1][j],mx[i][j+1],d[i][j].fi});
}
}
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
if(d[i][j].fi>max(mx[i][j+1],mx[i+1][j]))ans+=d[i][j].se;
}
}
printf("Case #%d: %lld\n",cas,ans);
}
return 0;
}