HDU - 3642 Get The Treasury(线段树求体积交)

时间:2021-08-21 21:06:49

https://cn.vjudge.net/problem/HDU-3642

题意

求立方体相交至少3次的体积。

分析

三维的呢。。首先解决至少覆盖三次的问题。则用三个标记,更新时的细节要注意。

注意到z比较小,于是枚举z一层层求,先求出在这一层的面积交,再乘上前后z的差值,就是体积了。注意离散化。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define eps 0.0000000001
#define IOS ios::sync_with_stdio(0);cin.tie(0);
#define random(a, b) rand()*rand()%(b-a+1)+a
#define pi acos(-1)
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
const int maxn = + ;
const int maxm = + ;
const int mod = ; int n;
int z[maxn];
int y[maxn];
struct LINE{
int x;
int y1,y2;
int z1,z2;
int flag;
bool operator <(const LINE &a)const{
return x<a.x;
}
}line[maxn];
struct ND{
int l,r;
int cover;
bool f;
int one;//覆盖一次以上的长度
int two;//覆盖两次以上的长度
int more;
}tree[maxn<<];
void build(int rt,int l,int r){
tree[rt].l=y[l];
tree[rt].r=y[r];
tree[rt].cover=;
tree[rt].one=tree[rt].two=tree[rt].more=;
tree[rt].f=false;
if(l+==r){
tree[rt].f=true;
return;
}
int mid = (l+r)>>;
build(rt<<,l,mid);
build(rt<<|,mid,r);
} void cal(int rt){
if(tree[rt].cover>=){
tree[rt].more=tree[rt].r-tree[rt].l;
tree[rt].one=tree[rt].two=;
}else if(tree[rt].cover==){
if(tree[rt].f){
tree[rt].more=;
tree[rt].two=tree[rt].r-tree[rt].l;
tree[rt].one=;
}else{
tree[rt].more=tree[rt<<].one+tree[rt<<].two+tree[rt<<].more+
tree[rt<<|].one+tree[rt<<|].two+tree[rt<<|].more;
tree[rt].two=tree[rt].r-tree[rt].l-tree[rt].more;
tree[rt].one=;
}
}else if(tree[rt].cover==){
if(tree[rt].f){
tree[rt].more=;
tree[rt].two=;
tree[rt].one=tree[rt].r-tree[rt].l;
}else{
tree[rt].more=tree[rt<<].two+tree[rt<<].more+
tree[rt<<|].two+tree[rt<<|].more;
tree[rt].two=tree[rt<<].one+tree[rt<<|].one;
tree[rt].one=tree[rt].r-tree[rt].l-tree[rt].more-tree[rt].two;
}
}else{
if(tree[rt].f){
tree[rt].more=tree[rt].one=tree[rt].two=;
}else{
tree[rt].one=tree[rt<<].one+tree[rt<<|].one;
tree[rt].more=tree[rt<<].more+tree[rt<<|].more;
tree[rt].two=tree[rt<<].two+tree[rt<<|].two;
}
}
}
void update(int rt,double l,double r,int flag){
if(l==tree[rt].l&&r==tree[rt].r){
tree[rt].cover+=flag;
cal(rt);
return;
}
if(tree[rt<<].r>=r) update(rt<<,l,r,flag);
else if(l>=tree[rt<<|].l) update(rt<<|,l,r,flag);
else{
update(rt<<,l,tree[rt<<].r,flag);
update(rt<<|,tree[rt<<|].l,r,flag);
}
cal(rt);
}
LINE tmp[maxn];
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int T,cas=;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
int cnt=;
int x1,x2,y1,y2,z1,z2;
for(int i=;i<n;i++){
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
z[cnt]=z1;
y[cnt]=y1;
line[cnt].x=x1;
line[cnt].y1=y1;
line[cnt].y2=y2;
line[cnt].z1=z1;
line[cnt].z2=z2;
line[cnt++].flag=; z[cnt]=z2;
y[cnt]=y2;
line[cnt].x=x2;
line[cnt].y1=y1;
line[cnt].y2=y2;
line[cnt].z1=z1;
line[cnt].z2=z2;
line[cnt++].flag=-;
}
sort(y,y+cnt);
sort(line,line+cnt);
int t1=unique(y,y+cnt)-y;
build(,,t1-);
sort(z,z+cnt);
int t2=unique(z,z+cnt)-z;
ll ans=;
ll area=;
for(int i=;i<t2-;i++){
int m=;
for(int j=;j<cnt;j++){
if(line[j].z1<=z[i]&&line[j].z2>z[i])
tmp[m++]=line[j];
}
area=;
update(,tmp[].y1,tmp[].y2,tmp[].flag);
for(int j=;j<m;j++){
area+=1ll*tree[].more*(tmp[j].x-tmp[j-].x);
update(,tmp[j].y1,tmp[j].y2,tmp[j].flag);
}
ans+=area*(z[i+]-z[i]);
}
printf("Case %d: %lld\n",cas++,ans);
}
return ;
}