题目链接
题目描述
你有一个
N
×
N
N \times N
N×N 的棋盘,每个格子内有一个整数,初始时的时候全部为
0
0
0 ,现在需要维护两种操作:
1 x y A
1 ≤ x , y ≤ N 1\le x,y\le N 1≤x,y≤N, A A A 是正整数。将格子x
,y
里的数字加上 A A A2 x1 y1 x2 y2
1 ≤ x 1 ≤ x 2 ≤ N 1 \le x_1 \le x_2 \le N 1≤x1≤x2≤N, 1 ≤ y 1 ≤ y 2 ≤ N 1 \le y_1\le y_2 \le N 1≤y1≤y2≤N。输出 x 1 , y 1 , x 2 , y 2 x_1, y_1, x_2, y_2 x1,y1,x2,y2 这个矩形内的数字和3
无 终止程序
输入格式
输入文件第一行一个正整数
N
N
N 。
接下来每行一个操作。每条命令除第一个数字之外,均要异或上一次输出的答案last_ans
,初始时last_ans
=
0
=0
=0。
输出格式
对于每个
2
2
2 操作,输出一个对应的答案。
输入输出样例
输入 #1
4
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3
输出 #1
3
5
说明/提示
1
<
=
N
<
=
500000
1<=N<=500000
1<=N<=500000 ,操作数不超过
200000
200000
200000 个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。
#include<bits/stdc++.h>
using namespace std;
inline int qr() {
int f = 0, fu = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')fu = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
f = (f << 3) + (f << 1) + c - 48;
c = getchar();
}
return f * fu;
}
const int N = 2e5 + 10;
const double alpha = 0.75;
struct K_D_Tree {
int d[N], lc[N], rc[N];
int xl, xr, yl, yr, cur, rt;
int siz[N], sum[N];
struct node {
int x, y, v;
} p[N];
int L[N], R[N], D[N], U[N];
int g[N];
inline void update(int x) {
sum[x] = sum[lc[x]] + sum[rc[x]] + p[x].v;
siz[x] = siz[lc[x]] + siz[rc[x]] + 1;
L[x] = R[x] = p[x].x, D[x] = U[x] = p[x].y;
if (lc[x]) {
L[x] = min(L[x], L[lc[x]]), R[x] = max(R[x], R[lc[x]]);
D[x] = min(D[x], D[lc[x]]), U[x] = max(U[x], U[lc[x]]);
}
if (rc[x]) {
L[x] = min(L[x], L[rc[x]]), R[x] = max(R[x], R[rc[x]]);
D[x] = min(D[x], D[rc[x]]), U[x] = max(U[x], U[rc[x]]);
}
}
int build(int l, int r) {
if (l > r)return 0;
int mid = (l + r) >> 1;
double avx = 0, avy = 0, vax = 0, vay = 0;
for (int i = l; i <= r; i++)avx += p[g[i]].x, avy += p[g[i]].y;
avx /= 1.0 * (r - l + 1), avy /= 1.0 * (r - l + 1);
for (int i = l; i <= r; i++) {
vax += (p[g[i]].x - avx) * (p[g[i]].x - avx);
vay += (p[g[i]].y - avy) * (p[g[i]].y - avy);
}
if (vax > vay)
nth_element(g + l, g + mid, g + r + 1, [&](int i, int j) {
return p[i].x < p[j].x;
}), d[g[mid]] = 1;
else
nth_element(g + l, g + mid, g + r + 1, [&](int i, int j) {
return p[i].y < p[j].y;
}), d[g[mid]] = 2;
lc[g[mid]] = build(l, mid - 1), rc[g[mid]] = build(mid + 1, r), update(g[mid]);
return g[mid];
}
int q[N];
void insert(int &x, int v) {
if (!x) return update(x = v), void();
insert(((d[x] == 1 ? p[v].x <= p[x].x : p[v].y <= p[x].y) ? lc : rc)[x], v);
update(x);
if (alpha * siz[x] <= (double) max(siz[lc[x]], siz[rc[x]])) {
int t = 0, l = 1, r = 1;
q[1] = x;
while (l <= r) {
int u = g[++t] = q[l++];
if (lc[u])q[++r] = lc[u];
if (rc[u])q[++r] = rc[u];
}
x = build(1, t);
}
}
int ans;
int query(int x) {
if (!x || xr < L[x] || xl > R[x] || yr < D[x] || yl > U[x])return 0;
if (xl <= L[x] && R[x] <= xr && yl <= D[x] && U[x] <= yr)return sum[x];
int res = 0;
if (xl <= p[x].x && p[x].x <= xr && yl <= p[x].y && p[x].y <= yr)res = p[x].v;
return query(lc[x]) + query(rc[x]) + res;
}
inline void change(int x, int y, int v) {
p[++cur] = {x ^ ans, y ^ ans, v ^ ans};
insert(rt, cur);
}
inline int ask(int _xl, int _xr, int _yl, int _yr) {
xl = _xl ^ ans, yl = _yl ^ ans, xr = _xr ^ ans, yr = _yr ^ ans;
return ans = query(rt);
}
} K;
int main() {
qr();
while (true)
switch (qr()) {
case 1: {
int x = qr(), y = qr(), v = qr();
K.change(x, y, v);
break;
}
case 2: {
int xl = qr(), yl = qr(), xr = qr(), yr = qr();
printf("%d\n", K.ask(xl, xr, yl, yr));
break;
}
default:
return 0;
}
}