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 = 20000 + 10; const int maxm = 200000 + 10; const int mod = 10007; 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<<2]; void build(int rt,int l,int r){ tree[rt].l=y[l]; tree[rt].r=y[r]; tree[rt].cover=0; tree[rt].one=tree[rt].two=tree[rt].more=0; tree[rt].f=false; if(l+1==r){ tree[rt].f=true; return; } int mid = (l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid,r); } void cal(int rt){ if(tree[rt].cover>=3){ tree[rt].more=tree[rt].r-tree[rt].l; tree[rt].one=tree[rt].two=0; }else if(tree[rt].cover==2){ if(tree[rt].f){ tree[rt].more=0; tree[rt].two=tree[rt].r-tree[rt].l; tree[rt].one=0; }else{ tree[rt].more=tree[rt<<1].one+tree[rt<<1].two+tree[rt<<1].more+ tree[rt<<1|1].one+tree[rt<<1|1].two+tree[rt<<1|1].more; tree[rt].two=tree[rt].r-tree[rt].l-tree[rt].more; tree[rt].one=0; } }else if(tree[rt].cover==1){ if(tree[rt].f){ tree[rt].more=0; tree[rt].two=0; tree[rt].one=tree[rt].r-tree[rt].l; }else{ tree[rt].more=tree[rt<<1].two+tree[rt<<1].more+ tree[rt<<1|1].two+tree[rt<<1|1].more; tree[rt].two=tree[rt<<1].one+tree[rt<<1|1].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=0; }else{ tree[rt].one=tree[rt<<1].one+tree[rt<<1|1].one; tree[rt].more=tree[rt<<1].more+tree[rt<<1|1].more; tree[rt].two=tree[rt<<1].two+tree[rt<<1|1].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<<1].r>=r) update(rt<<1,l,r,flag); else if(l>=tree[rt<<1|1].l) update(rt<<1|1,l,r,flag); else{ update(rt<<1,l,tree[rt<<1].r,flag); update(rt<<1|1,tree[rt<<1|1].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=1; scanf("%d",&T); while(T--){ scanf("%d",&n); int cnt=0; int x1,x2,y1,y2,z1,z2; for(int i=0;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=1; 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=-1; } sort(y,y+cnt); sort(line,line+cnt); int t1=unique(y,y+cnt)-y; build(1,0,t1-1); sort(z,z+cnt); int t2=unique(z,z+cnt)-z; ll ans=0; ll area=0; for(int i=0;i<t2-1;i++){ int m=0; for(int j=0;j<cnt;j++){ if(line[j].z1<=z[i]&&line[j].z2>z[i]) tmp[m++]=line[j]; } area=0; update(1,tmp[0].y1,tmp[0].y2,tmp[0].flag); for(int j=1;j<m;j++){ area+=1ll*tree[1].more*(tmp[j].x-tmp[j-1].x); update(1,tmp[j].y1,tmp[j].y2,tmp[j].flag); } ans+=area*(z[i+1]-z[i]); } printf("Case %d: %lld ",cas++,ans); } return 0; }