扫描线一边扫一边算期望,细节比较多。
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define PLI pair<LL, int>
#define PLL pair<LL, LL>
#define ull unsigned long long
using namespace std; const int N = 4e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ;
const double eps = 1e-; int n, m, tot, X[N], cntx, Y[N], cnty, zero[N], zero2[N], people, people2;
double val[N], val2[N], sum[N], fact[N], fact2[N], ret, ans; struct qus {
int y, x1, x2, op;
} a[N];
struct Point {
int x, y;
double p[];
} b[N]; struct Bit {
int a[N];
void modify(int x, int v) {
for(int i = x; i < N; i+=i&-i)
a[i] += v;
}
int sum(int x) {
int ans = ;
for(int i = x; i; i-=i&-i)
ans += a[i];
return ans;
}
} bit; vector<Point> point[N];
vector<PII> in[N], out[N]; inline void changed(int x, double p) {
if(zero[x] > ) return;
if(p < eps) fact[x] = val[x];
else fact[x] /= p;
}
inline void changem(int x, double p) {
fact[x] *= p;
}
inline void changed2(int y, double p) {
if(zero2[y] > ) return;
if(p < eps) fact2[y] = val2[y];
else fact2[y] /= p;
}
inline void changem2(int x, double p) {
fact2[x] *= p;
} int main() {
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
a[++tot] = qus{y1, x1, x2, };
a[++tot] = qus{y2, x1, x2, -};
X[++cntx] = x1; X[++cntx] = x2;
Y[++cnty] = y1; Y[++cnty] = y2;
}
for(int i = ; i <= m; i++) {
scanf("%d%d%lf%lf", &b[i].x, &b[i].y, &b[i].p[], &b[i].p[]);
b[i].p[]/=, b[i].p[] /= , b[i].p[] = - b[i].p[] - b[i].p[];
X[++cntx] = b[i].x; Y[++cnty] = b[i].y;
}
sort(X+, X++cntx); sort(Y+, Y++cnty);
cntx = unique(X+, X++cntx)-X-;
cnty = unique(Y+, Y++cnty)-Y-;
for(int i = ; i <= cntx; i++) val[i] = 1.0;
for(int i = ; i <= cnty; i++) val2[i] = 1.0;
for(int i = ; i <= tot; i++) {
a[i].y = lower_bound(Y+, Y++cnty, a[i].y)-Y;
a[i].x1 = lower_bound(X+, X++cntx, a[i].x1)-X;
a[i].x2 = lower_bound(X+, X++cntx, a[i].x2)-X;
if(a[i].op == ) in[a[i].y].push_back(mk(a[i].x1, a[i].x2));
else out[a[i].y].push_back(mk(a[i].x1, a[i].x2));
}
for(int i = ; i <= m; i++) {
b[i].x = lower_bound(X+, X++cntx, b[i].x)-X;
b[i].y = lower_bound(Y+, Y++cnty, b[i].y)-Y;
if(-b[i].p[] > eps) val[b[i].x] *= (-b[i].p[]);
else zero[b[i].x]++;
if(-b[i].p[] > eps) val2[b[i].y] *= (-b[i].p[]);
else zero2[b[i].y]++;
point[b[i].y].push_back(b[i]);
} for(int i = ; i <= cntx; i++) {
if(zero[i]) fact[i] = ;
else fact[i] = val[i];
sum[i] = sum[i-] + fact[i];
}
for(int i = ; i <= cnty; i++) {
if(zero2[i]) fact2[i] = ;
else fact2[i] = val2[i];
}
for(int i = ; i <= cnty; i++) {
ans += (Y[i]-Y[i-]-)*(people-ret);
for(PII sgm : in[i]) {
people += sgm.se-sgm.fi+;
people2 += X[sgm.se]-X[sgm.fi]+-(sgm.se-sgm.fi+);
ret += sum[sgm.se] - sum[sgm.fi-];
bit.modify(sgm.fi, );
bit.modify(sgm.se+, -);
}
double res1 = ret, res2 = ;
for(Point p : point[i]) {
if(!bit.sum(p.x)) continue;
res1 -= fact[p.x];
changed(p.x, -p.p[]);
changed2(p.y, -p.p[]);
res2 += fact[p.x]*fact2[p.y]*p.p[];
changem(p.x, -p.p[]);
changem2(p.y, -p.p[]);
}
ans += people - (fact2[i]*res1 + res2) + people2*(-fact2[i]);
for(PII sgm : out[i]) {
people -= sgm.se-sgm.fi+;
people2 -= X[sgm.se]-X[sgm.fi]+-(sgm.se-sgm.fi+);
ret -= sum[sgm.se] - sum[sgm.fi-];
bit.modify(sgm.fi, -);
bit.modify(sgm.se+, );
}
}
printf("%.12f\n", ans);
return ;
} /*
*/