P4148 WA 20pts,求条
/*Code By Manipula*/
#include <bits/stdc++.h>
#define endl '\n'
#define INF 0x3f3f3f3f
// #define int long long
#define fi first
#define sc second
#define lb lower_bound
#define YES printf("YES\n")
#define Yes printf("Yes\n")
#define NO printf("NO\n")
#define No printf("No\n")
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(fmt, arg...) fprintf(stderr, fmt, ##arg)
#define DEBUG() debug("In Function [%s] Line %d\n", __FUNCTION__, __LINE__)
const int N = 2e5 + 5;
const double alpha = 0.75;
struct Point {
int x[2], val;
Point() {}
Point(int _x, int _y, int val) : val(val) {
x[0] = _x; x[1] = _y;
}
} a[N];
int fr[N];
int n, rt, tot, top, lstAns;
namespace KD_Tree {
struct Node {
int ls, rs, Min[2], Max[2], sum, siz;
Point P;
#define ls(p) (tr[p].ls)
#define rs(p) (tr[p].rs)
} tr[N];
void init() {
tr[0].Min[0] = tr[0].Min[1] = INF;
tr[0].Max[0] = tr[0].Max[1] = -INF;
}
void pushup(int p) {
auto L = tr[ls(p)], R = tr[rs(p)];
tr[p].sum = tr[p].P.val + L.sum + R.sum;
tr[p].siz = L.siz + R.siz + 1;
for (int i = 0; i <= 1; i++) {
tr[p].Min[i] = tr[p].Max[i] = tr[p].P.x[i];
if (ls(p))tr[p].Min[i] = std::min(tr[p].Min[i], L.Min[i]);
if (rs(p))tr[p].Min[i] = std::min(tr[p].Min[i], R.Min[i]);
if (ls(p))tr[p].Max[i] = std::max(tr[p].Max[i], L.Max[i]);
if (rs(p))tr[p].Max[i] = std::max(tr[p].Max[i], R.Max[i]);
}
}
int Add() { return !top ? ++tot : fr[top--]; }
int Rebuild(int l, int r, int D) {
if (l > r)return 0;
int mid = (l + r) >> 1;
int p = Add();
std::nth_element(a + l, a + mid, a + r + 1, [&](Point A, Point B) { return A.x[D] < B.x[D]; });
tr[p].P = a[mid];
ls(p) = Rebuild(l, mid - 1, D ^ 1);
rs(p) = Rebuild(mid + 1, r, D ^ 1);
pushup(p);
return p;
}
void slap(int p, int cnt) {
if (ls(p))slap(ls(p), cnt);
a[tr[ls(p)].siz + cnt + 1] = tr[fr[++top] = p].P;
if (rs(p))slap(rs(p), tr[rs(p)].siz + cnt + 1);
}
void Work(int &p, int D) {
if (tr[p].siz * alpha <= tr[ls(p)].siz || tr[p].siz * alpha <= tr[rs(p)].siz)
slap(p, 0), p = Rebuild(1, tr[p].siz, D);
}
void Insert(int &p, Point P, int D) {
if (!p)return p = Add(), ls(p) = rs(p) = 0, tr[p].P = P, pushup(p);
if (P.x[D] <= tr[p].P.x[D])Insert(ls(p), P, D ^ 1);
else Insert(rs(p), P, D ^ 1);
pushup(p);
Work(p, D);
}
int Query(int p, int x1, int y1, int x2, int y2) {
if (!p)return 0;
if (x1 <= tr[p].Min[0] && tr[p].Max[0] <= x2 && y1 <= tr[p].Max[1] && tr[p].Max[1] <= y2)
return tr[p].sum;
if (tr[p].Max[0] < x1 || x2 < tr[p].Min[0] || tr[p].Max[1] < y1 || y2 < tr[p].Min[1])
return 0;
int ans = 0;
if (x1 <= tr[p].P.x[0] && tr[p].P.x[0] <= x2 && y1 <= tr[p].P.x[1] && tr[p].P.x[1] <= y2)
ans += tr[p].P.val;
ans += Query(ls(p), x1, y1, x2, y2) + Query(rs(p), x1, y1, x2, y2);
return ans;
}
}
signed main() {
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
int opt;
scanf("%d", &n);
KD_Tree::init();
while (scanf("%d", &opt), opt != 3) {
if (opt == 1) {
int x, y, k; scanf("%d%d%d", &x, &y, &k);
x ^= lstAns, y ^= lstAns, k ^= lstAns;
KD_Tree::Insert(rt, Point(x, y, k), 0);
}
else {
int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
x1 ^= lstAns, x2 ^= lstAns, y1 ^= lstAns, y2 ^= lstAns;
printf("%d\n", lstAns = KD_Tree::Query(rt, x1, y1, x2, y2));
}
}
return 0;
}