附上BC的官方题解。。。
题目关键在于在x轴和y轴上,鱼的坐标变化都是单调的,因为 d 是正值。
我们把在一个矩形内部有多少个点的询问拆分成四个在某个点的左下角
有多少个点的询问,然后用一棵线段树维护鱼的x坐标,一棵线段树维
护鱼的y坐标。对于移动操作,在对应的线段树上进行区间更新,更新
完成后询问该区间内的最大值,若最大值超过了我们关心的值,那么
这个点就可以删掉了,删除的方法可以通过在对应的线段树上把值设
为 −INF ,同时继续询问直到最大值不大于我们关心的值为止。那
么我们就可以实时维护当前在我们关心的点左下角的点有哪些了,这
可以再借助于一个树状数组。这样子作四遍我们就能得到最终的答案
了。由于每一次的过程中每个点只会被删除一次,所以复杂度
是 O((n+q)∗logn)) 。
#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 100005
#define maxm 100005
#define eps 1e-7
#define mod 1000000007
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
#define pii pair<int, int>
#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head
struct Point
{
int x, y;
Point(int x = 0, int y = 0) : x(x), y(y) {}
}point[4], fish[maxn];
int xmaxv[4][maxn << 2];
int ymaxv[4][maxn << 2];
int xlazy[4][maxn << 2];
int ylazy[4][maxn << 2];
int idx[4][maxn << 2];
int idy[4][maxn << 2];
int Sum[4][maxn << 2];
int a[maxn];
int b[maxn];
int n, m;
void pushup(int maxv[], int id[], int o)
{
if(maxv[ls] > maxv[rs]) maxv[o] = maxv[ls], id[o] = id[ls];
else maxv[o] = maxv[rs], id[o] = id[rs];
}
void pushup(int sum[], int o)
{
sum[o] = sum[ls] + sum[rs];
}
void pushdown(int maxv[], int lazy[], int o)
{
if(lazy[o]) {
maxv[ls] += lazy[o];
maxv[rs] += lazy[o];
lazy[ls] += lazy[o];
lazy[rs] += lazy[o];
lazy[o] = 0;
}
}
void build(int maxv[], int lazy[], int id[], int data[], int o, int L, int R)
{
lazy[o] = 0;
if(L == R) {
maxv[o] = data[L];
id[o] = L;
return;
}
int mid = (L + R) >> 1;
build(maxv, lazy, id, data, lson);
build(maxv, lazy, id, data, rson);
pushup(maxv, id, o);
}
void build(int sum[], int o, int L, int R)
{
if(L == R) {
sum[o] = 1;
return;
}
int mid = (L + R) >> 1;
build(sum, lson);
build(sum, rson);
pushup(sum, o);
}
void update(int maxv[], int lazy[], int id[], int o, int L, int R, int q)
{
if(L == R) {
maxv[o] = -INF;
return;
}
pushdown(maxv, lazy, o);
int mid = (L + R) >> 1;
if(q <= mid) update(maxv, lazy, id, lson, q);
else update(maxv, lazy, id, rson, q);
pushup(maxv, id, o);
}
void update(int sum[], int o, int L, int R, int q)
{
if(L == R) {
sum[o] = 0;
return;
}
int mid = (L + R) >> 1;
if(q <= mid) update(sum, lson, q);
else update(sum, rson, q);
pushup(sum, o);
}
void update(int maxv[], int lazy[], int id[], int o, int L, int R, int ql, int qr, int d)
{
if(ql <= L && qr >= R) {
maxv[o] += d;
lazy[o] += d;
return;
}
pushdown(maxv, lazy, o);
int mid = (L + R) >> 1;
if(ql <= mid) update(maxv, lazy, id, lson, ql, qr, d);
if(qr > mid) update(maxv, lazy, id, rson, ql, qr, d);
pushup(maxv, id, o);
}
bool check(int rt, int flag)
{
if(flag == 0) {
if(xmaxv[rt][1] > point[rt].x) {
update(Sum[rt], 1, 1, n, idx[rt][1]);
update(xmaxv[rt], xlazy[rt], idx[rt], 1, 1, n, idx[rt][1]);
return true;
}
return false;
}
else {
if(ymaxv[rt][1] > point[rt].y) {
update(Sum[rt], 1, 1, n, idy[rt][1]);
update(ymaxv[rt], ylazy[rt], idy[rt], 1, 1, n, idy[rt][1]);
return true;
}
return false;
}
}
int query(int sum[], int o, int L, int R, int ql, int qr)
{
if(ql <= L && qr >= R) return sum[o];
int mid = (L + R) >> 1, ans = 0;
if(ql <= mid) ans += query(sum, lson, ql, qr);
if(qr > mid) ans += query(sum, rson, ql, qr);
return ans;
}
void solve1()
{
int l, r, d;
scanf("%d%d%d", &l, &r, &d);
for(int i = 0; i < 4; i++) update(xmaxv[i], xlazy[i], idx[i], 1, 1, n, l, r, d);
for(int i = 0; i < 4; i++) while(check(i, 0));
}
void solve2()
{
int l, r, d;
scanf("%d%d%d", &l, &r, &d);
for(int i = 0; i < 4; i++) update(ymaxv[i], ylazy[i], idy[i], 1, 1, n, l, r, d);
for(int i = 0; i < 4; i++) while(check(i, 1));
}
void solve3()
{
int l, r;
scanf("%d%d", &l, &r);
int res = query(Sum[0], 1, 1, n, l, r) + query(Sum[3], 1, 1, n, l, r);
res -= query(Sum[1], 1, 1, n, l, r) + query(Sum[2], 1, 1, n, l, r);
printf("%d\n", res);
}
void work()
{
int xx1, yy1, xx2, yy2;
scanf("%d", &n);
scanf("%d%d%d%d", &xx1, &yy1, &xx2, &yy2);
point[0] = Point(xx1 - 1, yy1 - 1);
point[1] = Point(xx1 - 1, yy2);
point[2] = Point(xx2, yy1 - 1);
point[3] = Point(xx2, yy2);
for(int i = 1; i <= n; i++) scanf("%d%d", &a[i], &b[i]);
for(int i = 0; i < 4; i++) {
build(xmaxv[i], xlazy[i], idx[i], a, 1, 1, n);
build(ymaxv[i], ylazy[i], idy[i], b, 1, 1, n);
build(Sum[i], 1, 1, n);
}
for(int i = 0; i < 4; i++) while(check(i, 0));
for(int i = 0; i < 4; i++) while(check(i, 1));
scanf("%d", &m);
while(m--) {
int op;
scanf("%d", &op);
if(op == 1) solve1();
if(op == 2) solve2();
if(op == 3) solve3();
}
}
int main()
{
int _;
scanf("%d", &_);
while(_--) work();
return 0;
}