供自己复习使用,因此只贴代码。
题目链接:https://www.luogu.com.cn/problem/P4148。
代码
时间复杂度 \(\mathcal{O}(n\sqrt n)\)。
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#define int long long
#define N 200005
#define isdigit(ch) ('0' <= ch && ch <= '9')
using namespace std;
template<typename T>
void read(T&x) {x = 0;int f = 1;char ch = getchar();for (;!isdigit(ch);ch = getchar()) f = (ch == '-' ? -1 : f);for (;isdigit(ch);ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);x *= f;
}
const double alpha = 0.75;
struct node{int lson,rson;int d[2],mnd[2],mxd[2];int val,sum,sz;
}tr[N];
#define ls(x) (tr[x].lson)
#define rs(x) (tr[x].rson)
int root,cnt;
int g[N],tot;
void pushup(int x) {tr[x].sz = tr[ls(x)].sz + tr[rs(x)].sz + 1;tr[x].sum = tr[ls(x)].sum + tr[rs(x)].sum + tr[x].val;for (int i = 0;i < 2;i ++) {tr[x].mnd[i] = tr[x].mxd[i] = tr[x].d[i];tr[x].mnd[i] = min(min(tr[x].mnd[i],tr[ls(x)].mnd[i]),tr[rs(x)].mnd[i]);tr[x].mxd[i] = max(max(tr[x].mxd[i],tr[ls(x)].mxd[i]),tr[rs(x)].mxd[i]);}
}
void flatten(int cur) {if (!cur) return;flatten(ls(cur));g[++tot] = cur;flatten(rs(cur));
}
int build(int l,int r,int k) {if (l > r) return 0;int mid = l + r >> 1;nth_element(g + l,g + mid,g + r + 1,[k](int x,int y) {return tr[x].d[k] < tr[y].d[k];});int now = g[mid];tr[now].lson = build(l,mid - 1,k ^ 1),tr[now].rson = build(mid + 1,r,k ^ 1);pushup(now);return now;
}
void insert(int &now,int x,int y,int val,int k) {if (!now) {now = ++cnt;tr[now].lson = tr[now].rson = 0;tr[now].d[0] = x,tr[now].d[1] = y;tr[now].val = tr[now].sum = val;tr[now].sz = 1;tr[now].mnd[0] = tr[now].mxd[0] = x;tr[now].mnd[1] = tr[now].mxd[1] = y;return;}if (tr[now].d[0] == x && tr[now].d[1] == y) {tr[now].val += val;tr[now].sum += val;return ;}if ((k == 0 && x < tr[now].d[0]) || (k == 1 && y < tr[now].d[1])) insert(ls(now),x,y,val,k ^ 1);else insert(rs(now),x,y,val,k ^ 1);pushup(now);if (tr[ls(now)].sz > 1.0 * tr[now].sz * alpha || tr[rs(now)].sz > 1.0 * tr[now].sz * alpha) {tot = 0;flatten(now);now = build(1,tot,k);}
}
int query(int now,int x1,int y1,int x2,int y2) {if (!now) return 0;if (tr[now].mnd[0] >= x1 && tr[now].mxd[0] <= x2 && tr[now].mnd[1] >= y1 && tr[now].mxd[1] <= y2) return tr[now].sum;if (tr[now].mxd[0] < x1 || tr[now].mnd[0] > x2 || tr[now].mxd[1] < y1 || tr[now].mnd[1] > y2) return 0;int res = 0;if (tr[now].d[0] >= x1 && tr[now].d[0] <= x2 && tr[now].d[1] >= y1 && tr[now].d[1] <= y2) res += tr[now].val;return res + query(ls(now),x1,y1,x2,y2) + query(rs(now),x1,y1,x2,y2);
}
signed main(){tr[0].mnd[0] = tr[0].mnd[1] = 1e9;tr[0].mxd[0] = tr[0].mxd[1] = -1e9;int n;cin >> n;for (int lst = 0;1;) {int op,x,y,a,x2,y2;read(op);if (op == 1) {read(x),read(y),read(a);x ^= lst,y ^= lst,a ^= lst;insert(root,x,y,a,0);}else if (op == 2) {read(x),read(y),read(x2),read(y2);x ^= lst,y ^=lst,x2 ^= lst,y2 ^= lst;lst = query(root,x,y,x2,y2);printf("%lld\n",lst);}else return 0;}return 0;
}