题意:
给你N个矩形,每个矩形给出左下角坐标,右上角坐标,有M个询问,每个询问给出一个时间t,问(0,0),(t,t)的范围内矩形的面积和(重叠的也算)。
解析:
真的是细节非常难处理的题目,从有思路到AC,整整敲了一天。
由于矩形之间是相互独立的,而且 ti 又不大,可以把思路转化为每个矩形对时间的贡献是多少。
如果是一个矩形,可以转化成一个正方形,外加一个矩形的情况。
正方形,每增加一秒,其面积对 t 的贡献是一个等差数列的等差数列。
而一个矩形,每增加一秒,其面积对t 的贡献是一个等差数列。
用差分前缀和,求出到每个时刻,加了多少面积。
注意细节。
my code
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 200005;
int n, m;
ll sum[MAXN], d1[MAXN], d2[MAXN];
void init() {
memset(sum, 0, sizeof(sum));
memset(d1, 0, sizeof(d1));
memset(d2, 0, sizeof(d2));
}
ll cal(ll a1, ll D1, ll D2, ll n) {
return a1 + n*D1 + n*(n+1)/2 * D2;
}
void add(ll L, ll R, ll a1, ll D1, ll D2) {
ll len = R - L + 1;
sum[L] += a1;
sum[R+1] -= cal(a1, D1, D2, len);
d1[L] += D1;
d1[R+1] -= D1 + D2 * len;
d2[L] += D2;
d2[R+1] -= D2;
}
void build() {
for(int i = 1; i < MAXN; i++) {
d2[i] += d2[i-1];
d1[i] += d1[i-1] + d2[i];
sum[i] += sum[i-1] + d1[i];
}
}
void solve(int x1, int y1, int x2, int y2) {
if(x1 > y1) {
swap(x1, y1);
swap(x2, y2);
}
ll a1, D1;
ll maxLen = max(min(x2, y2) - y1, 0);
add(y1, y1 + maxLen - 1, 0, y1 - x1 -1, 2);
if(x2 < y2) {
a1 = (ll)(x2 - x1) * maxLen;
D1 = x2 - x1;
add((ll)y1 + maxLen, y2-1, a1, D1, 0);
}else {
a1 = (ll)(y2 - y1) * (y2 - x1);
D1 = y2 - y1;
add((ll)y1 + maxLen, x2-1, a1, D1, 0);
}
a1 = (ll)(y2 - y1) * (x2 - x1);
add(max(x2, y2), MAXN, a1, 0, 0);
}
int main() {
int x1, y1, x2, y2, ti;
int T;
scanf("%d", &T);
while(T--) {
init();
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
solve(x1, y1, x2, y2);
}
build();
scanf("%d", &m);
while(m--) {
scanf("%d", &ti);
printf("%lld\n", sum[ti-1]);
}
}
return 0;
}