hdu 3642 Get The Treasury (线段树+扫描线,求长方体体积交)

hdu3642题目链接

题意:给出若干个(1000)长方体,求至少交三次的空间的体积。

尺寸为[x1,x2],[y1,y2],[z1,z2],其中x,y的坐标的绝对值不超过1E6,Z的坐标的绝对值不超过1E9.

思路:

线段树+扫描线。

由于Z的坐标范围比较小,我们的做法是 利用“微分”的思想,将每个长方体,想成若干的高度为1的矩形(矩形片)

因此就转化成了求矩形至少交三次的面积

其中和矩形交,也就是矩形至少交2次的面积比较类似,只不过线段树多维护一个至少三次覆盖的长度的域。

 1void PushUp(int l,int r,int rt)
 2{
 3    //cout<<"l:"<<l<<" r:"<<r<<" rt:"<<rt<<" id:"<<id<<endl;
 4    if (tree[rt].cnt>=3)
 5    {
 6        tree[rt].one = tree[rt].two = tree[rt].three = X[r+1]-X[l];
 7    }
 8    else 
 9    if (tree[rt].cnt==2)
10    {
11    tree[rt].one = tree[rt].two = X[r+1]-X[l];
12
13    if (l==r) tree[rt].three = 0 ;
14    else tree[rt].three = tree[rt<<1].one + tree[rt<<1|1].one;
15
16    }else if (tree[rt].cnt==1)
17    {
18        tree[rt].one = X[r+1] - X[l];
19
20    if (l==r) tree[rt].two = tree[rt].three = 0;
21    else 
22    {
23        tree[rt].two = tree[rt<<1].one + tree[rt<<1|1].one;
24        tree[rt].three = tree[rt<<1].two + tree[rt<<1|1].two;
25    }
26    }
27    else
28    {
29    if (l==r) tree[rt].one = tree[rt].two =  tree[rt].three = 0;
30    else 
31    {
32        tree[rt].one = tree[rt<<1].one + tree[rt<<1|1].one;
33        tree[rt].two = tree[rt<<1].two + tree[rt<<1|1].two;
34        tree[rt].three = tree[rt<<1].three + tree[rt<<1|1].three;
35    }
36    }
37}

假设我们有一个长为5,宽为6,高为7的长方体

那么我们就要将其拆成7个,长为5,宽为6的矩形

将所有长方体处理完之后,枚举高度,对于每一个高度,如果矩形大于等于三个,就做一个“矩形的三次面积交”操作,将答案累加。

2A,PushUp的时候写错了一句。。。即如果父亲节点已经覆盖了两次,那么父亲节点被覆盖三次的是从左右儿子被覆盖一次的情况得来的

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2017年09月28日 星期四 14时18分35秒
  4File Name :hdu3642.cpp
  5************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#define PB push_back
 20#define fst first
 21#define sec second
 22#define lson l,m,rt<<1
 23#define rson m+1,r,rt<<1|1
 24#define ms(a,x) memset(a,x,sizeof(a))
 25typedef long long LL;
 26#define pi pair < int ,int >
 27#define MP make_pair
 28
 29using namespace std;
 30const double eps = 1E-8;
 31const int dx4[4]={1,0,0,-1};
 32const int dy4[4]={0,-1,1,0};
 33const int inf = 0x3f3f3f3f;
 34const int N=2E3+7;
 35int n;
 36struct Seg
 37{
 38    LL l,r,h;
 39    int d;
 40    Seg(){}
 41    Seg(LL l,LL r,LL h,int d):l(l),r(r),h(h),d(d){}
 42    bool operator < (const Seg & rhs)const
 43    {
 44    return h < rhs.h;
 45    }
 46}a[N];
 47struct Tree
 48{
 49    LL one,two,three;
 50    int cnt;
 51}tree[N<<2];
 52LL X[N],Z[N];
 53struct Cube
 54{
 55    LL  x1,y1,z1,x2,y2,z2;
 56}cube[N];
 57struct Rec
 58{
 59    LL x1,y1,x2,y2;
 60    void print()
 61    {
 62    printf("x1:%lld y1:%lld x2:%lld y2:%lld\n",x1,y1,x2,y2);
 63    }
 64    Rec(){}
 65    Rec(LL x1, LL y1,LL x2, LL y2):x1(x1),y1(y1),x2(x2),y2(y2){}
 66};
 67vector< Rec >rec[N];
 68void PushUp(int l,int r,int rt)
 69{
 70    //cout<<"l:"<<l<<" r:"<<r<<" rt:"<<rt<<" id:"<<id<<endl;
 71    if (tree[rt].cnt>=3)
 72    {
 73        tree[rt].one = tree[rt].two = tree[rt].three = X[r+1]-X[l];
 74    }
 75    else 
 76    if (tree[rt].cnt==2)
 77    {
 78    tree[rt].one = tree[rt].two = X[r+1]-X[l];
 79
 80    if (l==r) tree[rt].three = 0 ;
 81    else tree[rt].three = tree[rt<<1].one + tree[rt<<1|1].one;
 82
 83    }else if (tree[rt].cnt==1)
 84    {
 85        tree[rt].one = X[r+1] - X[l];
 86
 87    if (l==r) tree[rt].two = tree[rt].three = 0;
 88    else 
 89    {
 90        tree[rt].two = tree[rt<<1].one + tree[rt<<1|1].one;
 91        tree[rt].three = tree[rt<<1].two + tree[rt<<1|1].two;
 92    }
 93    }
 94    else
 95    {
 96    if (l==r) tree[rt].one = tree[rt].two =  tree[rt].three = 0;
 97    else 
 98    {
 99        tree[rt].one = tree[rt<<1].one + tree[rt<<1|1].one;
100        tree[rt].two = tree[rt<<1].two + tree[rt<<1|1].two;
101        tree[rt].three = tree[rt<<1].three + tree[rt<<1|1].three;
102    }
103    }
104}
105void update( int L,int R,int val,int l,int r,int rt)
106{
107    if (L<=l && r<=R)
108    {
109    tree[rt].cnt +=val;
110    PushUp(l,r,rt);
111    return;
112    }
113    int m = (l+r)>>1;
114    if (L<=m) update(L,R,val,lson);
115    if (R>=m+1) update(L,R,val,rson);
116    PushUp(l,r,rt);
117}
118
119LL solve( int z)
120{
121    int siz = rec[z].size();
122    if (siz<3) return 0LL;
123   // for ( int i = 0 ; i < siz ; i++) rec[z][i].print();
124    ms(tree,0);
125    for ( int i = 0 ; i < siz ; i++)
126    {
127    LL x1 = rec[z][i].x1;
128    LL y1 = rec[z][i].y1;
129    LL x2 = rec[z][i].x2;
130    LL y2 = rec[z][i].y2;
131//  printf("x1:%lld y1:%lld x2:%lld y2:%lld\n",x1,y1,x2,y2);
132    X[i+1] = x1;
133    X[i+1+siz] = x2;
134    a[i+1]=Seg(x1,x2,y1,1);
135    a[i+1+siz]=Seg(x1,x2,y2,-1);
136    }
137    siz<<=1;
138    sort(X+1,X+siz+1);
139    sort(a+1,a+siz+1);
140    int m = unique(X+1,X+siz+1)-X-1;
141    LL ret = 0;
142    for ( int i = 1 ; i < siz; i++)
143    {
144    int l = lower_bound(X+1,X+m+1,a[i].l)-X;
145    int r = lower_bound(X+1,X+m+1,a[i].r)-X;
146    update(l,r-1,a[i].d,1,m,1);
147    ret += tree[1].three * (a[i+1].h-a[i].h);
148    }
149    //cout<<"Z:"<<z<<" ret:"<<ret<<endl;
150    return ret;
151}
152int main()
153{
154    #ifndef  ONLINE_JUDGE 
155    freopen("./in.txt","r",stdin);
156  #endif
157    int T;
158    int cas =  0;
159    cin>>T;
160    while (T--)
161    {
162        scanf("%d",&n);
163        ms(tree,0);
164        for ( int i = 0 ; i < N ; i++) rec[i].clear();
165        for ( int i = 1 ; i <= n ; i++)
166        {
167        scanf("%lld %lld %lld",&cube[i].x1,&cube[i].y1,&cube[i].z1);
168        scanf("%lld %lld %lld",&cube[i].x2,&cube[i].y2,&cube[i].z2);
169        //此处先存储下来是为了将Z坐标离散化
170        Z[i] = cube[i].z1;
171        Z[i+n] = cube[i].z2;
172        for ( int j = cube[i].z1 ; j < cube[i].z2 ; j++)
173        {
174                    rec[j+500].PB(Rec(cube[i].x1,cube[i].y1,cube[i].x2,cube[i].y2));
175        }
176        }
177        LL ans = 0;
178        for ( int i = 0 ; i <=1000 ; i++)
179        {
180        ans += solve(i);
181        }
182        printf("Case %d: %lld\n",++cas,ans);
183    }
184  #ifndef ONLINE_JUDGE  
185  fclose(stdin);
186  #endif
187    return 0;
188}