2 1 1 25 0 0 10 10 1 2 2 5 2 0 0 2 1 1 1 0 3 2 2
Case 1: 2500 Case 2: 16
题意:
原始题意就不说了。抽象出来就是给你n个底面在xoy平面与坐标轴平行的立方体。他们之间可以重叠。问体积并是多少。
思路:
和求面积并的思路类似。用高度(价值)把立方体分成很多段。然后一段一段求体积就好。
详细见代码:
#include<cstdio> #include<algorithm> #include<iostream> using namespace std; const int maxn=30010; typedef long long ll; #define lson L,mid,ls #define rson mid+1,R,rs struct node { int x1,x2,h,tag;//面积并用的值。tag表示加边还是减边 int p;//存第三维高度。 node(){} node(int a,int b,int c,int d,int e):x1(a),x2(b),h(c),tag(d),p(e){} bool operator <(const node &op) const { return h<op.h; } } seg[maxn<<1],tmp[maxn<<1]; int val[maxn],H[maxn<<1]; int len[maxn<<3],cov[maxn<<3]; void build(int L,int R,int rt) { cov[rt]=len[rt]=0; if(L==R) return; int ls=rt<<1,rs=ls|1,mid=(L+R)>>1; build(lson); build(rson); } void update(int L,int R,int rt,int l,int r,int d) { if(l<=L&&R<=r) { cov[rt]+=d; len[rt]=cov[rt]?H[R+1]-H[L]:(L==R?0:len[rt<<1]+len[rt<<1|1]); //printf("%d -> %d len %d\n",H[L],H[R+1],len[rt]); return; } int ls=rt<<1,rs=ls|1,mid=(L+R)>>1; if(l<=mid) update(lson,l,r,d); if(r>mid) update(rson,l,r,d); len[rt]=cov[rt]?H[R+1]-H[L]:len[ls]+len[rs]; //printf("%d -> %d len %d\n",H[L],H[R+1],len[rt]); } int main() { int t,n,m,i,j,cas=1,ct,cnt; int x1,x2,y1,y2,ch,ns; ll ans,tp; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=1;i<=m;i++) scanf("%d",&val[i]); ans=ns=ct=0; for(i=1;i<=n;i++) { scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&ch); seg[ns++]=node(x1,x2,y1,1,val[ch]); seg[ns++]=node(x1,x2,y2,-1,val[ch]); H[ct++]=x1,H[ct++]=x2; } sort(H,H+ct); ct=unique(H,H+ct)-H; sort(seg,seg+ns); sort(val+1,val+m+1); for(i=0;i<m;i++) { for(j=cnt=0;j<ns;j++) if(seg[j].p>val[i]) tmp[cnt++]=seg[j]; build(0,ct-2,1); for(j=tp=0,cnt--;j<cnt;j++) { int l=lower_bound(H,H+ct,tmp[j].x1)-H; int r=lower_bound(H,H+ct,tmp[j].x2)-H-1; update(0,ct-2,1,l,r,tmp[j].tag); tp+=(ll)len[1]*(tmp[j+1].h-tmp[j].h);//注意ll.算面积并 } ans+=tp*(val[i+1]-val[i]);//面积乘高就是体积了。 } printf("Case %d: %I64d\n",cas++,ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/bossup/article/details/47685091