线段树变形~
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 #define inf 0x3f3f3f3f 8 typedef long long ll; 9 const int N=1010; 10 11 int y[N<<1],z[N<<1]; 12 13 struct node 14 { 15 int l,r,c,lf,rf; 16 int one,two,more; 17 } tree[N<<3]; 18 19 struct Line 20 { 21 int f,z1,z2;//f矩形入边左1,出边右-1 22 int x,up,down;//线段的横坐标、上下纵坐标 23 } line[N<<1],b[N<<1]; 24 25 bool cmp1(Line x,Line y) 26 { 27 return x.x<y.x; 28 } 29 30 void build(int i,int L,int R) 31 { 32 tree[i].l=L,tree[i].r=R; 33 tree[i].c=0; 34 tree[i].lf=y[L]; 35 tree[i].rf=y[R]; 36 tree[i].one=tree[i].two=tree[i].more=0; 37 if(L+1==R) 38 return ; 39 int mid=(L+R)>>1; 40 build(i<<1,L,mid); 41 build(i<<1|1,mid,R); 42 } 43 44 void pushup(int i) 45 { 46 if(tree[i].c>=3) 47 { 48 tree[i].more=tree[i].rf-tree[i].lf; 49 tree[i].one=tree[i].two=0; 50 //return; 51 } 52 else if(tree[i].c==2)//两次 53 { 54 if(tree[i].l+1==tree[i].r) 55 { 56 tree[i].more=0; 57 tree[i].two=tree[i].rf-tree[i].lf; 58 tree[i].one=0; 59 return; 60 } 61 tree[i].more=tree[i<<1].one+tree[i<<1].two+tree[i<<1].more+tree[i<<1|1].one+tree[i<<1|1].two+tree[i<<1|1].more; 62 tree[i].two=tree[i].rf-tree[i].lf-tree[i].more; 63 tree[i].one=0; 64 } 65 else if(tree[i].c==1)//一次 66 { 67 if(tree[i].l+1==tree[i].r) 68 { 69 tree[i].more=0; 70 tree[i].two=0; 71 tree[i].one=tree[i].rf-tree[i].lf; 72 return; 73 } 74 tree[i].more=tree[i<<1].more+tree[i<<1].two+tree[i<<1|1].more+tree[i<<1|1].two; 75 tree[i].two=tree[i<<1].one+tree[i<<1|1].one; 76 tree[i].one=tree[i].rf-tree[i].lf-tree[i].more-tree[i].two; 77 } 78 else 79 { 80 if(tree[i].l+1==tree[i].r) 81 { 82 tree[i].more=tree[i].one=tree[i].two=0; 83 return; 84 } 85 tree[i].more=tree[i<<1].more+tree[i<<1|1].more; 86 tree[i].two=tree[i<<1].two+tree[i<<1|1].two; 87 tree[i].one=tree[i<<1].one+tree[i<<1|1].one; 88 } 89 } 90 91 void update(int i,Line a)//加入一条新线段、更新线段树 92 { 93 if(a.down<=tree[i].lf&&tree[i].rf<=a.up) 94 { 95 tree[i].c+=a.f; 96 pushup(i); 97 return; 98 } 99 if(a.up<=tree[i<<1].rf) 100 update(i<<1,a); 101 else if(a.down>=tree[i<<1|1].lf) 102 update(i<<1|1,a); 103 else 104 { 105 Line b=a; 106 b.up=tree[i<<1].rf; 107 update(i<<1,b); 108 Line c=a; 109 c.down=tree[i<<1|1].lf; 110 update(i<<1|1,c); 111 } 112 pushup(i); 113 } 114 115 int main() 116 { 117 int t,n,tt=1; 118 scanf("%d",&t); 119 while(t--) 120 { 121 scanf("%d",&n); 122 int k=0; 123 for(int i=1;i<=n;i++) 124 { 125 int x1,y1,z1,x2,up,z2; 126 scanf("%d %d %d %d %d %d",&x1,&y1,&z1,&x2,&up,&z2); 127 line[k].x=x1,line[k].down=y1,line[k].up=up; 128 line[k].z1=z1,line[k].z2=z2; 129 line[k].f=1,y[k]=y1,z[k++]=z1; 130 line[k].x=x2,line[k].down=y1,line[k].up=up; 131 line[k].z1=z1,line[k].z2=z2; 132 line[k].f=-1,y[k]=up,z[k++]=z2; 133 } 134 sort(line,line+k,cmp1); 135 sort(y,y+k); 136 int x=unique(y,y+k)-y; 137 build(1,0,x-1); 138 sort(z,z+k); 139 int xx=unique(z,z+k)-z; 140 ll ans=0; 141 for(int i=0;i<xx-1;i++) 142 { 143 int p=0; 144 for(int j=0;j<k;j++) 145 { 146 if(line[j].z1<=z[i]&&line[j].z2>z[i]) 147 b[p++]=line[j]; 148 } 149 ll w=0; 150 update(1,b[0]); 151 for(int j=1;j<p;j++) 152 { 153 w+=(ll)tree[1].more*(b[j].x-b[j-1].x); 154 update(1,b[j]); 155 } 156 ans+=w*(z[i+1]-z[i]); 157 } 158 printf("Case %d: %lld\n",tt++,ans); 159 } 160 return 0; 161 }