艾莎女王又开始用冰雪魔法盖宫殿了。
她决定先造一堵墙,于是释放魔法让形为直角梯形的冰砖从天而降,定入冻土之中。
现在你将回答女王的询问:某段冻土上冰砖的面积。
注:多块冰砖之间会互相重叠,重叠部分要多次计算。
Input
第一行一个整数n,表示有n个冰砖先后定入了冻土之中。
冻土上刚开始并没有冰砖。
接下来n行,每行6个整数,x1i,h1i,x2i,h2i,li,ri。
表示一次如图所示的冰砖下落,并询问在这之后,落在[li,ri]内冰砖的总面积。
2≤n≤100000,−108≤li<ri≤108,−108≤x1i<x2i≤108,0≤h1i,h2i≤10000,x2i−x1i≤105
Output
输出n行,每行输出一个浮点数,作为对该询问的回答。误差小于1e-6的回答都被当作正确回答
解题报告
首先由于范围很大,我们对X轴上的点进行离散化
注意到这个四边形就是给一段区间增加一段等差数列.
并且注意到等差数列叠加后依然还是等差数列
那么我们在线段树中就存储四个值:
1.double st; //该区间左端应该加的值
2.double ed; //该区间右端应该加的值
3.double k; //等差数列的k值,不多说
4.double sum; //该区间的面积之和
那么面积我们就转换成梯形计算:
SUM = (st + ed) * 0.5 * Len; //注意到这个Len是这个区间的实际长度!!
这样.
还有两点需要注意!
1.区间建立的时候是[L,R] → [L,mid] + [mid,R]
2. updata操作有三种情况,三种情况的更新各不同,这点需要注意
分别对应ql ,qr 在mid 的左 / 右 / 中三种情况,需分开讨论
注意上以上几点,那么本题也就迎刃而解了.
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 1e5 + 500; 7 int n; 8 int pos[maxn*9]; 9 int hashpos[maxn*9]; 10 11 typedef struct Query 12 { 13 int l,r,x1,y1,x2,y2,id[6]; 14 }; 15 16 typedef struct Data 17 { 18 int l,r,len; 19 double sum,st,ed,k; 20 void updata(const double &x,const double &y,const double &z) 21 { 22 st += x; 23 ed += y; 24 k += z; 25 sum += (double)(x+y)*len*0.5; 26 } 27 }; 28 29 30 Query q[maxn*2]; 31 Data tree[maxn*6]; 32 int size = 0; 33 34 35 void push_up(int cur) 36 { 37 tree[cur].sum = tree[cur*2].sum + tree[cur*2+1].sum; 38 } 39 40 inline double get_(int x1,int x2,double st,double k) 41 { 42 return (double)(hashpos[x2]-hashpos[x1]) * k + st; 43 } 44 45 46 void push_down(int cur) 47 { 48 double st = tree[cur].st; 49 double ed = tree[cur].ed; 50 double k = tree[cur].k; 51 int l = tree[cur].l; 52 int r = tree[cur].r; 53 int mid = l + (r-l)/2; 54 double news = get_(tree[cur].l,mid,st,k); 55 tree[2*cur].updata(st,news,k); 56 tree[2*cur+1].updata(news,ed,k); 57 tree[cur].st = tree[cur].ed = tree[cur].k = 0.; 58 } 59 60 void build_tree(int cur,int l,int r) 61 { 62 tree[cur].l = l , tree[cur].r = r; 63 tree[cur].len = hashpos[r] - hashpos[l]; 64 tree[cur].st = tree[cur].ed = tree[cur].k = tree[cur].sum = 0.; 65 if (r -l > 1) 66 { 67 int mid = l + (r-l)/2; 68 build_tree(2*cur,l,mid); 69 build_tree(2*cur+1,mid,r); 70 } 71 } 72 73 void updata(int ql,int qr,int cur,double st,double ed,double k) 74 { 75 int l = tree[cur].l , r = tree[cur].r; 76 if (l >= ql && r <= qr) 77 { 78 tree[cur].updata(st,ed,k); 79 } 80 else 81 { 82 push_down(cur); 83 int mid = l + (r-l) / 2; 84 //三种情况,分开讨论 85 if (qr <= mid) updata(ql,qr,2*cur,st,ed,k); 86 else if(ql >= mid) updata(ql,qr,2*cur+1,st,ed,k); 87 else 88 { 89 double news = get_(ql,mid,st,k); 90 updata(ql,mid,2*cur,st,news,k); 91 updata(mid,qr,2*cur+1,news,ed,k); 92 } 93 push_up(cur); 94 } 95 } 96 97 double query(int ql,int qr,int cur) 98 { 99 int l = tree[cur].l , r = tree[cur].r; 100 if (l >= ql && r <= qr) 101 return tree[cur].sum; 102 else 103 { 104 push_down(cur); 105 double res = 0.; 106 int mid = l + (r-l)/2; 107 if (mid > ql) 108 res += query(ql,qr,2*cur); 109 if (mid < qr) 110 res += query(ql,qr,2*cur+1); 111 push_up(cur); 112 return res; 113 } 114 } 115 116 inline double getk(int x1,int x2,int y1,int y2) 117 { 118 return (double)(y2-y1) / (double)(x2-x1); 119 } 120 121 122 123 int main(int argc,char *argv[]) 124 { 125 scanf("%d",&n); 126 for(int i = 0 ; i < n ; ++ i) 127 { 128 int x1,y1,x2,y2,l,r; 129 scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&l,&r); 130 q[i].id[0] = size; 131 pos[size++] = x1; 132 q[i].id[1] = size; 133 pos[size++] = x2; 134 q[i].id[2] = size; 135 pos[size++] = l; 136 q[i].id[3] = size; 137 pos[size++] = r; 138 q[i].x1 = x1; 139 q[i].x2 = x2; 140 q[i].y1 = y1; 141 q[i].y2 = y2; 142 q[i].l = l; 143 q[i].r = r; 144 } 145 memcpy(hashpos,pos,sizeof(int)*size); 146 sort(hashpos,hashpos+size); 147 int c = unique(hashpos,hashpos+size) - hashpos; 148 for(int i = 0 ; i < size ; ++ i) 149 pos[i] = lower_bound(hashpos,hashpos+c,pos[i]) - hashpos; 150 build_tree(1,0,c-1); 151 for(int i = 0 ; i < n ; ++ i) 152 { 153 int x1 = q[i].x1; 154 int y1 = q[i].y1; 155 int x2 = q[i].x2; 156 int y2 = q[i].y2; 157 double k = getk(x1,x2,y1,y2); 158 updata(pos[q[i].id[0]],pos[q[i].id[1]],1,(double)y1,(double)y2,k); 159 double res = query(pos[q[i].id[2]],pos[q[i].id[3]],1); 160 printf("%.9lf\n",res); 161 } 162 return 0; 163 }
时间: 2024-10-16 05:03:32