艾尔大停电2
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)Submit Status
(剧情提要:请看上题)
阿塔尼斯的新式矩形能量场成功的研制出来了。但是实验过程中却发现了一个巨大的问题,一股神秘的东方力量影响了新式能量场,两个能量场互相覆盖的区域将会互相抵消,变回无能量场区。
有趣的是,如果这个区域被第三个能量场覆盖,它将仍是有效的能量场区,当然如果有第四个能量场,那么就会和第三个能量场抵消,又变成无能量场区……也就是说,一个能量场将会把它范围内的能量场区变为非能量场区,把非能量场区变为能量场区。
现在,阿塔尼斯正在建造一些能量场,你需要知道某些时刻某个坐标点上是否是有效的能量场区。
Input
(注意能量场形式与上题的不同)本题有多组数据。第一行一个正整数T(T<=10)表示数据的组数。
每组数据第一行一个正整数N(N<=50000),表示操作的次数。
接下来N行形容按时间顺序进行的N次操作,每行可能有两种形式:
1、一个大写字母C和四个正整数 C x1 y1 x2 y2 (1 <= x1 <= x2 <= 1000, 1 <= y1 <= y2 <= 1000) 表示以(x1,y1)为左下角(x2,y2)为右上角建造一个平行坐标轴的矩形能量场(包括边界)。
2、一个大写字母Q和两个正整数 Q x y (1 <= x, y <= 1000) 表示询问坐标(x,y)是否是有效的能量场区。
Output
对于每个询问输出一行一个整数。如果是有效的能量场区输出1,否则输出0。Sample input and output
Sample Input Sample Output1
10
C 2 1 2 2
Q 2 2
C 2 1 2 1
Q 1 1
C 1 1 2 1
C 1 2 1 2
C 1 1 2 2
Q 1 1
C 1 1 2 1
Q 2 1
1
0
0
1
Source
2017 UESTC Training for Data Structures
My Solution
题意:每次对一个矩形更新操作,单点查询,求该点被更新的次数。
二维树状数组+区间更新
用二维树状数组, get(x, y)表示 1,1到x,y这个矩形的面积或者说矩阵的元素和,
所以对于读入的每个x1,y1,x2,y2。
可以在 (x1, y1)这里插入一个1,然后为了抵消影响在(x2+1, y2+1)插入一个 -1,
在(x2+1, y1)和(x1, y2+1)也插入一个-1,
这就是树状数组区间更新的常用做法,推广到二维也是一样。
这里如果查询x > x2+1, y > y2+1,的时候会有 k个1和3*k个-1,但并没有影响,
3*(-1) + 1 = -2也表示0,故没有影响。
查询的时候直接 get(x,y),然后while(ans < 0)则加一个偶数;从而变成非负整数,
输出ans%2即可
复杂度 O(n*n*logn*logn)
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int MAXN = 1e3 + 8;
int Tree[MAXN][MAXN];
inline int lowbit(int x)
{
return (x & -x);
}
inline int add(int x, int y, int value)
{
int i, j;
for (i = x; i < MAXN; i += lowbit(i)){
for (j = y; j < MAXN; j += lowbit(j)){
Tree[i][j] += value;
}
}
}
inline int get(int x, int y)
{
int res = 0, i, j;
for (i = x; i; i -= lowbit(i)){
for (j = y; j; j -= lowbit(j)){
res += Tree[i][j];
}
}
return res;
}
//!@ProLights
/**
前面陈斐童在我电脑上交过题,后来去上课了。
刚刚写完不小心用他(没有 Logout)的号交了一发,
希望查重的时候看看我这里的注释,谢谢
**/
int main() {
#ifdef LOCAL
freopen("q.txt", "r", stdin);
//freopen("q.out", "w", stdout);
#endif // LOCAL
//ios::sync_with_stdio(false); cin.tie(0);
int T, n, i, x1, y1, x2, y2, ans;
char op;
scanf("%d", &T);
while(T--){
memset(Tree, 0, sizeof(Tree));
scanf("%d", &n);
while(n--){
getchar(); getchar();
op = getchar();
//cin >> op;
if(op == 'C'){
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
add(x2+1, y2+1, -1);
add(x2+1, y1, -1);
add(x1, y2+1, -1);
add(x1, y1, 1);
}
else{
scanf("%d%d", &x1, &y1);
ans = get(x1, y1);
while(ans < 0) ans += (MAXN*MAXN);
printf("%d\n", ans % 2);
}
}
}
return 0;
}
Thank you!
------from ProLights