传送门
题解:
首先是坐标切割,由于坐标移动单调,我们直接在某条鱼穿过渔网的某条线(向两端无限延伸后的)的时候重构整块。
调整块长卡常,现在是HDU rank1。
比那些写线段树的不知道快到哪里去了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;bool f=0;
while(!isdigit(c=gc()))f=c=='-';T num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return f?-num:num;
}
inline int getint(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int N=1e5+7;
#define x1 x_1
#define x2 x_2
#define y1 y_1
#define y2 y_2
int n,m;
int x1,x2,y1,y2;
int B,bcnt;
int bl[N],pl[N],pr[N],ans[N];
int x[N],y[N],addx[N],addy[N],nxtx[N],nxty[N];
inline void rebuild(int id){
ans[id]=0;nxtx[id]=0x3f3f3f3f,nxty[id]=0x3f3f3f3f;
for(int re i=pl[id];i<=pr[id];++i){
x[i]+=addx[id],y[i]+=addy[id];
if(x[i]>x2||y[i]>y2)continue;
(x1<=x[i]&&x[i]<=x2&&y1<=y[i]&&y[i]<=y2)&&(++ans[id]);
nxtx[id]=std::min(nxtx[id],x[i]<x1?x1-x[i]:x2+1-x[i]);
nxty[id]=std::min(nxty[id],y[i]<y1?y1-y[i]:y2+1-y[i]);
}
addx[id]=addy[id]=0;
}
inline void modify_x(int l,int r,int d){
if(bl[l]==bl[r]){
for(int re i=l;i<=r;++i)x[i]+=d;
rebuild(bl[l]);
return ;
}
if(l==pl[bl[l]])--l;
else {
for(int re i=l;i<=pr[bl[l]];++i)x[i]+=d;
rebuild(bl[l]);
}
if(r==pr[bl[r]])++r;
else {
for(int re i=r;i>=pl[bl[r]];--i)x[i]+=d;
rebuild(bl[r]);
}
for(int re i=bl[l]+1;i<bl[r];++i)if((addx[i]+=d)>=nxtx[i])rebuild(i);
}
inline void modify_y(int l,int r,int d){
if(bl[l]==bl[r]){
for(int re i=l;i<=r;++i)y[i]+=d;
rebuild(bl[l]);
return ;
}
if(l==pl[bl[l]])--l;
else {
for(int re i=l;i<=pr[bl[l]];++i)y[i]+=d;
rebuild(bl[l]);
}
if(r==pr[bl[r]])++r;
else {
for(int re i=r;i>=pl[bl[r]];--i)y[i]+=d;
rebuild(bl[r]);
}
for(int re i=bl[l]+1;i<bl[r];++i)if((addy[i]+=d)>=nxty[i])rebuild(i);
}
inline int query(int l,int r){int res=0;
if(bl[l]==bl[r]){
if(l==pl[bl[l]]&&r==pr[bl[r]])res=ans[bl[l]];
else for(int re i=l,dx=addx[bl[l]],dy=addy[bl[l]];i<=r;++i)res+=(x1<=x[i]+dx&&x[i]+dx<=x2&&y1<=y[i]+dy&&y[i]+dy<=y2);
return res;
}
if(l==pl[bl[l]])res+=ans[bl[l]];
else{
for(int re i=l,dx=addx[bl[l]],dy=addy[bl[l]];i<=pr[bl[l]];++i)
res+=(x1<=x[i]+dx&&x[i]+dx<=x2&&y1<=y[i]+dy&&y[i]+dy<=y2);
}
if(r==pr[bl[r]])res+=ans[bl[r]];
else {
for(int re i=r,dx=addx[bl[r]],dy=addy[bl[r]];i>=pl[bl[r]];--i)
res+=(x1<=x[i]+dx&&x[i]+dx<=x2&&y1<=y[i]+dy&&y[i]+dy<=y2);
}
for(int re i=bl[l]+1;i<bl[r];++i)res+=ans[i];
return res;
}
inline void solve(){
n=getint(),x1=getint(),y1=getint(),x2=getint(),y2=getint();B=std::max(1.0,sqrt(n)*0.27);bcnt=0;
for(int re i=1;i<=n;++i){
x[i]=getint(),y[i]=getint();
if((i-1)%B==0){
pl[++bcnt]=i;pr[bcnt-1]=i-1;
addx[bcnt]=addy[bcnt]=ans[bcnt]=0;
}
bl[i]=bcnt;
}bl[n+1]=bcnt+1;
for(int re i=1;i<=bcnt;++i)rebuild(i);
m=getint();int l,r,d;
while(m--)switch(getint()){
case 1:l=getint(),r=getint(),d=getint();modify_x(l,r,d);break;
case 2:l=getint(),r=getint(),d=getint();modify_y(l,r,d);break;
case 3:l=getint(),r=getint();cout<<query(l,r)<<"\n";break;
}
}
signed main(){
// freopen("fish.in","r",stdin);//freopen("fish.out","w",stdout);
int T=getint();
while(T--)solve();
return 0;
}