威威猫系列故事——晒被子
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 949 Accepted Submission(s): 235
Problem Description
因为马拉松初赛中吃鸡腿的题目让不少人抱憾而归,威威猫一直觉得愧对大家,这几天他悄悄搬到直角坐标系里去住了。
生活还要继续,太阳也照常升起,今天,威威猫在第一象限晒了N条矩形的被子,被子的每条边都和坐标轴平行,不同被子的某些部分可能会叠在一起。这时候,在原点处突然发了场洪水,时间t的时候,洪水会蔓延到( t, t ),即左下角为( 0, 0 ) ,右上角为( t, t )的矩形内都有水。
悲剧的威威猫想知道,在时间t1, t2, t3 ... tx 的时候,他有多少面积的被子是湿的?
生活还要继续,太阳也照常升起,今天,威威猫在第一象限晒了N条矩形的被子,被子的每条边都和坐标轴平行,不同被子的某些部分可能会叠在一起。这时候,在原点处突然发了场洪水,时间t的时候,洪水会蔓延到( t, t ),即左下角为( 0, 0 ) ,右上角为( t, t )的矩形内都有水。
悲剧的威威猫想知道,在时间t1, t2, t3 ... tx 的时候,他有多少面积的被子是湿的?
Input
输入数据首先包含一个正整数T,表示有T组测试数据;
每组数据的第一行首先是一个整数N,表示有N条被子;
接下来N行,每行包含四个整数x1, y1, x2, y2,代表一条被子的左下角和右上角的坐标;
然后接下来一行输入一个整数x,表示有x次询问;
再接下来x行,输入x个严格单调递增的整数,每行一个,表示威威猫想知道的时间ti。
[Technical Specification]
T <= 5
0 < N <= 20000
1 <= x1 < x2 <= 200000
1 <= y1 < y2 <= 200000
1 <= x <= 20000
1 <= ti <= 200000 (1 <= i <= x )
每组数据的第一行首先是一个整数N,表示有N条被子;
接下来N行,每行包含四个整数x1, y1, x2, y2,代表一条被子的左下角和右上角的坐标;
然后接下来一行输入一个整数x,表示有x次询问;
再接下来x行,输入x个严格单调递增的整数,每行一个,表示威威猫想知道的时间ti。
[Technical Specification]
T <= 5
0 < N <= 20000
1 <= x1 < x2 <= 200000
1 <= y1 < y2 <= 200000
1 <= x <= 20000
1 <= ti <= 200000 (1 <= i <= x )
Output
对于每次询问,请计算并输出ti时有多少面积的被子是湿的,每个输出占一行。
Sample Input
1 2 1 1 3 3 2 2 4 4 5 1 2 3 4 5
Sample Output
0 1 5 8 8
Source
思路: 滚动数组
分3部分加区间和。 A * t * t + B * t + C = answer
第一部分是
对任意一个矩形,在更新t1 ~ t2的区间: 即斜线阴影部分 面积的等于 (t - x1) * (t - y1) 化简得 t * t - (x1 + y1) t + x1*y1; 即 A = 1 , B = - ( x1 + y1) C = x1 * y1;
在更新t2 ~ t3 的区间 即竖线蓝色的阴影部分。 面积等于 (t - x1) * (t - y1) - (t - x2) * (t - y1) 化简得 (-(x1 + y1) + x2 + y1) * t + x1 * y1 - x2 * y1 即 A = 0, B= -(x1 + y1) + x2 + y1;
C = x1 * y1 - x2 * y1;
在更新区间 t3 ~ 200000时 即全部面积。 (y2 - y1) * (x2 - x1) 即 A = 0, B = 0, C = (y2 - y1) * (x2 - x1);
#include <cstdio>
#include <cstring>
const int v = 200005;
int T, N, x;
__int64 a, b, c, A[v], B[v], C[v];
void f(int s, int t) {
A[s] += a;
B[s] += b;
C[s] += c;
A[t + 1] += -a;
B[t + 1] += -b;
C[t + 1] += -c;
}
void insert(__int64 x1, __int64 y1, __int64 x2, __int64 y2) {
int m = x1 > y1 ? x1 : y1, t = x2 > y2 ? x2 : y2, t2 = x2 > y2 ? y2 : x2;
a = b = c = 0;
c = (x2 - x1) * (y2 - y1);
f(t + 1, v - 5);
a = 1;
b = -(x1 + y1);
c = x1 * y1;
if(t2 >= m)
f(m + 1, t2);
else
t2 = m;
if(y2 > x2) {
a -= 1;
b += x2 + y1;
c -= x2 * y1;
}
else if(x2 > y2) {
a -= 1;
b += x1 + y2;
c -= x1 * y2;
}
f(t2 + 1, t);
}
int main() {
scanf("%d", &T);
while(T--) {
memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));
memset(C, 0, sizeof(C));
scanf("%d", &N);
for(int i = 0; i < N; ++i) {
__int64 x1, y1, x2, y2;
scanf("%I64d%I64d%I64d%I64d", &x1, &y1, &x2, &y2);
insert(x1, y1, x2, y2);
}
for(int i = 1; i < v; ++i) {
A[i] += A[i-1];
B[i] += B[i-1];
C[i] += C[i-1];
}
scanf("%d", &x);
while(x--) {
__int64 t;
scanf("%I64d", &t);
printf("%I64d\n", t * t * A[t] + t * B[t] + C[t]);
}
}
}
#include <cstdio>
const int v = 600000;
const int size = 200000;
typedef struct node{
__int64 a, b, c;
int l, r;
}node;
node nod[v];
int T, N;
__int64 a, b, c;
void build(int root, int st, int ed) {
nod[root].l = st;
nod[root].r = ed;
nod[root]. a = nod[root].b = nod[root].c = 0;
if(ed != st) {
int mid = (st + ed) / 2;
build(root * 2, st, mid);
build(root * 2 + 1, mid + 1, ed);
}
}
void updata(int root, int l, int r) {
if(l > r)
return ;
if(nod[root].l == l && nod[root].r == r) {
nod[root].a += a;
nod[root].b += b;
nod[root].c += c;
return ;
}
int mid = (nod[root].l + nod[root].r) / 2;
if(r <= mid)
updata(root * 2, l, r);
else if(l > mid)
updata(root * 2 + 1, l, r);
else {
updata(root * 2, l, mid);
updata(root * 2 + 1, mid + 1, r);
}
}
__int64 Qurry(int root, __int64 t) {
if(nod[root].l == nod[root].r)
return t * t * nod[root].a + t * nod[root].b + nod[root].c;
nod[root * 2].a += nod[root].a;
nod[root * 2].b += nod[root].b;
nod[root * 2].c += nod[root].c;
nod[root * 2 + 1].a += nod[root].a;
nod[root * 2 + 1].b += nod[root].b;
nod[root * 2 + 1].c += nod[root].c;
nod[root].a = nod[root].b = nod[root].c = 0;
int mid = (nod[root].l + nod[root].r) / 2;
if(t <= mid)
return Qurry(2 * root, t);
else
return Qurry(2 * root + 1, t);
}
void insert(__int64 x1, __int64 y1, __int64 x2, __int64 y2) {
int m = x1 > y1 ? x1 : y1, t = x2 > y2 ? x2 : y2, t2 = x2 > y2 ? y2 : x2;
a = b = c = 0;
c = (x2 - x1) * (y2 - y1);
updata(1, t + 1, size);
a = 1;
b = -(x1 + y1);
c = x1 * y1;
if(t2 >= m)
updata(1, m + 1, t2);
else
t2 = m;
if(y2 > x2) {
a -= 1;
b += x2 + y1;
c -= x2 * y1;
}
else if(x2 > y2) {
a -= 1;
b += x1 + y2;
c -= x1 * y2;
}
updata(1, t2 + 1, t);
}
int main() {
int i, j, k, x;
__int64 x1, x2, y1, y2, t;
scanf("%d", &T);
while(T--) {
build(1, 1, size);
scanf("%d", &N);
for(i = 0; i < N; ++i) {
scanf("%I64d%I64d%I64d%I64d", &x1, &y1, &x2, &y2);
insert(x1, y1, x2, y2);
}
scanf("%d", &x);
while(x--) {
scanf("%I64d", &t);
printf("%I64d\n", Qurry(1, t));
}
}
}