hdu 3642 Get The Treasure
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 3642 Get The Treasure相关的知识,希望对你有一定的参考价值。
对于这题,一开始看到z值较小,就像枚举z坐标,然后对于一个单独的z平面做面积交来累加答案。。(三个以上柱体的体积交)
搜题解学完up函数的姿势后感觉自己写的还是蛮不错的嘛。。
线段树每个节点包含当前节店的覆盖次数cnt,表示覆盖次数-长度映射的数组,由于只要cnt>=3就可以统计,故数组只开到3。。
由于n只有1000,所以平面交的时候先对于x坐标进行离散化,然后就是扫描线。。
一开始自己的姿势是对于每个z建立一个线段树,但是会mle。。。后来才改成使用一个重复利用。。然后就是没注意到cnt会大于三可能会re到无法自拔(比如我)。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define inf 0x3f3f3f3f 5 #define mod 1000000007 6 #define LL 2*n 7 #define RR 2*n+1 8 #define lson l,mid,2*n 9 #define rson mid+1,r,2*n+1 10 #define mlt map<ll,ll>::iterator 11 #define mit map<int,int>::iterator 12 #define vi vector<int> 13 #define mii map<int,int> 14 #define msi map<string,int> 15 #define si set<int> 16 #define sit set<int>::iterator 17 #define slt set<l>::iterator 18 #define mp make_pair 19 #define pb push_back 20 #define pii pair<int,int> 21 #define pdd pair<double,double> 22 #define pi acos(-1) 23 const int maxn =2222; 24 struct Seg{ 25 int l , r , h , s; 26 Seg() {} 27 Seg(ll a,ll b,ll c,ll d):l(a) , r(b) , h(c) , s(d) {} 28 bool operator < (const Seg &cmp) const { 29 if (h == cmp.h) return s > cmp.s; 30 return h < cmp.h; 31 } 32 }ss[maxn<<2]; 33 int x[maxn<<2]; 34 struct node 35 { 36 int cnt,a[5]; 37 }tr[maxn<<2]; 38 int bin(int z,int n) 39 { 40 int l=0,r=n; 41 while(r-l>1) 42 { 43 int mid=(l+r)>>1; 44 if(x[mid]>=z) 45 r=mid; 46 else 47 l=mid; 48 } 49 return r; 50 } 51 void up(int l,int r,int n) 52 { 53 memset(tr[n].a,0,sizeof(tr[n].a)); 54 int cnt=min(3,tr[n].cnt); 55 if(l==r) 56 { 57 tr[n].a[cnt]=x[r+1]-x[l]; 58 return; 59 } 60 int tmp=x[r+1]-x[l]; 61 for(int i=0;i<=3;i++) 62 { 63 tr[n].a[min(cnt+i,3)]+=tr[LL].a[i]+tr[RR].a[i]; 64 } 65 for(int i=0;i<=3;i++) 66 tmp-=tr[n].a[i]; 67 tr[n].a[cnt]+=tmp; 68 } 69 void update(int l,int r,int n,int left,int right,int targ) 70 { 71 if(left<=l&&r<=right) 72 { 73 tr[n].cnt+=targ; 74 up(l,r,n); 75 return ; 76 } 77 int mid=(l+r)>>1; 78 if(left<=mid) 79 update(lson,left,right,targ); 80 if(right>mid) 81 update(rson,left,right,targ); 82 up(l,r,n); 83 } 84 int a[5000][20]; 85 int main() 86 { 87 int t,cas=1; 88 //freopen("C:\\Users\\Administrator\\Documents\\duipai\\data.txt","r",stdin);freopen("C:\\Users\\Administrator\\Documents\\duipai\\out1.txt","w",stdout); 89 scanf("%d",&t); 90 while(t--) 91 { 92 int n; 93 scanf("%d",&n); 94 for(int i=1;i<=n;i++) 95 { 96 for(int j=1;j<=6;j++) 97 scanf("%d",&a[i][j]); 98 } 99 ll ans=0; 100 for(int i=-500;i<=500;i++) 101 { 102 int num1=0,num=0; 103 for(int k=1;k<=n;k++) 104 { 105 if(i>=a[k][3]&&i<a[k][6]) 106 { 107 ss[++num]=Seg(a[k][1],a[k][4],a[k][2],1); 108 ss[++num]=Seg(a[k][1],a[k][4],a[k][5],-1); 109 } 110 } 111 sort(ss+1,ss+1+num); 112 for(int j=1;j<=num;j++) 113 { 114 x[++num1]=ss[j].l; 115 x[++num1]=ss[j].r; 116 } 117 sort(x+1,x+1+num1); 118 int tmp=1; 119 for(int j=2;j<=num1;j++) 120 { 121 if(x[j]!=x[j-1]) 122 x[++tmp]=x[j]; 123 } 124 num1=tmp; 125 for(int j=1;j<=num;j++) 126 { 127 int l=bin(ss[j].l,num1); 128 int r=bin(ss[j].r,num1)-1; 129 if(l<=r) 130 update(1,num1-1,1,l,r,ss[j].s); 131 ans+=1ll*tr[1].a[3]*(ss[j+1].h-ss[j].h); 132 } 133 } 134 printf("Case %d: %I64d\n",cas++,ans); 135 } 136 return 0; 137 }
以上是关于hdu 3642 Get The Treasure的主要内容,如果未能解决你的问题,请参考以下文章
HDU 3642 - Get The Treasury - [加强版扫描线+线段树]
HDU3642 Get The Treasury —— 求矩形交体积 线段树 + 扫描线 + 离散化
HDU-3642 Get The Treasury(扫描线 + 离散化 + 线段树)
Get The Treasury HDU - 3642(体积扫描线)