题意
二维平面上有 \(n\) 个点,有一个四边平行于坐标轴的渔网,同时平面上有 \(n\) 个编号为 \(1\) 到 \(n\) 点。
你需要支持 \(3\) 种操作:
1 l r d:编号在 \([l,r]\) 内的所有点向 \(x\) 轴正方向平移 \(d\) 个单位
1 l r d:编号在 \([l,r]\) 内的所有点向 \(y\) 轴正方向平移 \(d\) 个单位
3 l r:求渔网内有多少个点(在渔网边界上的点也算)
\(T\in [1,10]\) 组数据,\(1\le n,m\le 30000,\space 1\le d\le 10^9,\space x_1\le x_2,\space y_1\le y_2\)
题解
普及题,把渔网拆成 \(4\) 个左下角无限远的矩形,每个子问题变成只限制点的 \(x,y\) 坐标上限,每次操作前把越界的点删掉即可,这就只需要线段树支持单点删除和求区间最大值。最后容斥一下 \(4\) 个矩形的答案。
还是只想存下题。
#include<bits/stdc++.h>
#define ll long long
#define N 30005
#define lowbit(x) x&-x
const ll inf = 1e9 + 7;
using namespace std;
inline int read(){
int x=0; bool f=1; char c=getchar();
for(;!isdigit(c); c=getchar()) if(c=='-') f=0;
for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
if(f) return x; return 0-x;
}
int n,m,x1,Y1,x2,y2,p[N][2],ans[N];
struct query{int opt,l,r,d;}q[N];
struct SegTree{
#define ls o<<1
#define rs o<<1|1
ll mx[N<<2],tag[N<<2];
inline void pushdown(int o){
if(tag[o]){
mx[ls]+=tag[o], mx[rs]+=tag[o];
tag[ls]+=tag[o], tag[rs]+=tag[o];
tag[o]=0;
}
}
inline void pushup(int o){
mx[o]=max(mx[ls],mx[rs]);
}
void build(int o, int l, int r, int opt){
tag[o]=0;
if(l==r){mx[o]=p[l][opt]; return;}
int mid=(l+r)>>1;
build(ls,l,mid,opt);
build(rs,mid+1,r,opt);
pushup(o);
}
void mdf(int o, int l, int r, int L, int R, ll v){
if(L<=l && r<=R){
mx[o]+=v, tag[o]+=v;
return;
}
pushdown(o);
int mid=(l+r)>>1;
if(L<=mid) mdf(ls,l,mid,L,R,v);
if(R>mid) mdf(rs,mid+1,r,L,R,v);
pushup(o);
}
int query(int o, int l, int r){
if(l==r) return l;
pushdown(o);
int mid=(l+r)>>1;
return mx[ls]>mx[rs] ? query(ls,l,mid) : query(rs,mid+1,r);
}
}tx,ty;
int fwk[N];
void ins(int x,int v){for(; x<=n; x+=lowbit(x)) fwk[x]+=v;}
int ask(int x){
int res=0;
for(; x; x-=lowbit(x)) res+=fwk[x];
return res;
}
void calc(int x, int y, int v){
tx.build(1,1,n,0);
ty.build(1,1,n,1);
memset(fwk,0,sizeof(fwk));
for(int i=1; i<=n; i++) ins(i,1);
for(int i=1; i<=m; i++){
while(tx.mx[1]>x){
int p=tx.query(1,1,n);
tx.mdf(1,1,n,p,p,-inf);
if(ask(p)-ask(p-1)) ins(p,-1);
}
while(ty.mx[1]>y){
int p=ty.query(1,1,n);
ty.mdf(1,1,n,p,p,-inf);
if(ask(p)-ask(p-1)) ins(p,-1);
}
if(q[i].opt==1) tx.mdf(1,1,n,q[i].l,q[i].r,(ll)q[i].d);
if(q[i].opt==2) ty.mdf(1,1,n,q[i].l,q[i].r,(ll)q[i].d);
if(q[i].opt==3) ans[i] += v*(ask(q[i].r)-ask(q[i].l-1));
}
}
signed main(){
//freopen("c.in","r",stdin);
//freopen("std.out","w",stdout);
int T=read();
while(T--){
n=read();
x1=read(), Y1=read(), x2=read(), y2=read();
for(int i=1; i<=n; i++) p[i][0]=read(), p[i][1]=read();
m=read();
for(int i=1; i<=m; i++){
q[i].opt=read(), q[i].l=read(), q[i].r=read();
if(q[i].opt!=3) q[i].d=read();
ans[i]=0;
}
calc(x2,y2,1);
calc(x1-1,Y1-1,1), calc(x2,Y1-1,-1), calc(x1-1,y2,-1);
for(int i=1;i<=m;i++) if(q[i].opt==3) printf("%d\n",ans[i]);
}
return 0;
}