这道题唯一的一个难点应该就是如何去处理三维情况下的扫描线
这里其实我们可以这样想:先以Z轴为扫描线,然后我们单独考虑在此情况下的那个平面的样子,然后我们就可以将这个问题处理成了二维的面积相交问题。
但其实还是挺不好写的(主要还是我太菜了)
我们可以慢慢的理一下思路
首先我们可以想到这个线段树的pushdown操作其实是不需要的,因为每次查询的时候我们只需要知道根节点(整棵树)的情况即可,所以pushdown可以不用写了。
然后我们可以考虑一下题中给的数据范围,x和y的范围均为[-1e6,1e6],但是我们可以发现这个n的范围只有1e3所以我们可以考虑将这些点离散化一下。
处理好思路应该就好写很多了,不过写的时候要注意一些细节问题
#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<time.h>
#include<queue>
#include<unordered_map>
#include<stack>
#include<map>
#include<set>
#include<vector>
#define endl "\n"
#define x first
#define y second
#define Endl endl
#define int long long
typedef long long ll;
const int INF=0x7fffffff;
const double PI=3.14159265359;
using namespace std;
const int N=3e6+10;
vector<int>xx,yy,zz;//分别对x,y,z进行离散化
int idx;
struct point{
int l,r;
int cnt;
int sum1,sum2,sum3;//sumx记录被覆盖大于等于x次的长度
}tr[N*4];
struct edge{
int x1,x2,y1,y2,z1,z2;
}a[N];
struct pp{
int x1,x2;
int y;
int z1,z2;
int type;
bool operator <(const pp&a){
return y<a.y;
}
}s[N];
struct pppp{
int x1,x2;
int y;
int type;
}b[N];
int find(int x,int type){//find函数查找离散化之前的值
if(type==1) return xx[x];
else if(type==2) return yy[x];
else return zz[x];
}
void pushup(int root){//分别维护好sum1,sum2,sum3的值
int ch=root<<1;
if(tr[root].cnt>=3){
tr[root].sum3=find(tr[root].r+1,1)-find(tr[root].l,1);//这里对r加一的目的是因为我们已经把线段映射到数组中了,那么我们恢复的时候自然要进行+1的操作
tr[root].sum1=tr[root].sum2=tr[root].sum3;
}
else if(tr[root].cnt>=2){//该线段已经被覆盖两次了,所以该段中sum3的值应该该是两个儿子的sum1的值之和(这样可以省去pushdown的操作)
if(tr[root].l!=tr[root].r)
tr[root].sum3=tr[ch].sum1+tr[ch+1].sum1;
else tr[root].sum3=0;
tr[root].sum2=find(tr[root].r+1,1)-find(tr[root].l,1);
tr[root].sum1=tr[root].sum2;
}
else if(tr[root].cnt>=1){
if(tr[root].l!=tr[root].r){
tr[root].sum3=tr[ch].sum2+tr[ch+1].sum2;
tr[root].sum2=tr[ch].sum1+tr[ch+1].sum1;
}
else{
tr[root].sum3=tr[root].sum2=0;
}
tr[root].sum1=find(tr[root].r+1,1)-find(tr[root].l,1);
}
else{
if(tr[root].l!=tr[root].r){
tr[root].sum3=tr[ch].sum3+tr[ch+1].sum3;
tr[root].sum2=tr[ch].sum2+tr[ch+1].sum2;
tr[root].sum1=tr[ch].sum1+tr[ch+1].sum1;
}
else{
tr[root].sum3=tr[root].sum3=tr[root].sum1=0;
}
}
}
void build(int root,int l,int r){
tr[root].l=l;
tr[root].r=r;
tr[root].cnt=0;
tr[root].sum1=0;
tr[root].sum2=0;
tr[root].sum3=0;
if(l!=r){
int mid=(l+r)>>1;
int ch=root<<1;
build(ch,l,mid);
build(ch+1,mid+1,r);
}
}
void change(int root,int l,int r,int x){
if(tr[root].l==l&&tr[root].r==r){
tr[root].cnt+=x;
pushup(root);
return ;
}
int mid=(tr[root].l+tr[root].r)>>1;
int ch=root<<1;
if(r<=mid) change(ch,l,r,x);
else if(l>mid) change(ch+1,l,r,x);
else change(ch,l,mid,x),change(ch+1,mid+1,r,x);
pushup(root);
}
void solve(){
int cnt=0;
int ans=0;
xx.clear();
yy.clear();
zz.clear();
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x1>>a[i].y1>>a[i].z1>>a[i].x2>>a[i].y2>>a[i].z2;
xx.push_back(a[i].x1),xx.push_back(a[i].x2);
yy.push_back(a[i].y1),yy.push_back(a[i].y2);
zz.push_back(a[i].z1),zz.push_back(a[i].z2);
}
sort(xx.begin(),xx.end());
sort(yy.begin(),yy.end());
sort(zz.begin(),zz.end());
xx.erase(unique(xx.begin(),xx.end()),xx.end());
yy.erase(unique(yy.begin(),yy.end()),yy.end());
zz.erase(unique(zz.begin(),zz.end()),zz.end());
for(int i=1;i<=n;i++){
a[i].x1=lower_bound(xx.begin(),xx.end(),a[i].x1)-xx.begin();
a[i].x2=lower_bound(xx.begin(),xx.end(),a[i].x2)-xx.begin();
a[i].y1=lower_bound(yy.begin(),yy.end(),a[i].y1)-yy.begin();
a[i].y2=lower_bound(yy.begin(),yy.end(),a[i].y2)-yy.begin();
a[i].z1=lower_bound(zz.begin(),zz.end(),a[i].z1)-zz.begin();
a[i].z2=lower_bound(zz.begin(),zz.end(),a[i].z2)-zz.begin();
s[++cnt]={a[i].x1,a[i].x2,a[i].y1,a[i].z1,a[i].z2,1};
s[++cnt]={a[i].x1,a[i].x2,a[i].y2,a[i].z1,a[i].z2,-1};
}
sort(s+1,s+1+cnt);//按照y的大小排序
for(int i=0;i<zz.size()-1;i++){
build(1,0,xx.size());
int last=-1;
int tot=0;
int temp=find(i+1,3)-find(i,3);
for(int j=1;j<=cnt;j++){
if(s[j].z1<=i&&s[j].z2>i){
b[++tot]={s[j].x1,s[j].x2,s[j].y,s[j].type};//b记录满足要求的矩形
}
}
for(int j=1;j<=tot;j++){
int k1=b[j].x1,k2=b[j].x2-1;//这里减1的目的是将线段映射为数组
if(j!=1)
ans+=temp*(find(b[j].y,2)-find(b[j-1].y,2))*tr[1].sum3;
change(1,k1,k2,b[j].type);
}
}
cout<<"Case "<<++idx<<": "<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin>>T;
while(T--){
solve();
}
}