传送门
PROBLEM
SOL
//一开始看错了题面,以为“网”是动态的,头脑一片空白
既然渔网不动,又是以鱼的编号为下标询问,显然不能基于鱼的坐标解决问题
考虑暴力处理每一个修改,对于鱼的x坐标,只加不减(y坐标同理)。换而言之,如果鱼已出网,便可不用考虑。
一、将 X 1 , Y 1 , X 2 , Y 2 X1,Y1,X2,Y2 X1,Y1,X2,Y2看作四条分界线,用四个线段树分别维护原序列上某一段区间的鱼的x/y坐标有没有超过分界线。
二、维护区间最大值。
三、如果当前区间最大值增加后未超过,打个lazy标记 r e t u r n return return,否则暴力找到那些超过了分界线的点,把点值改为极小值(相当于忽略该点)。
四、复杂度分析:由于每一个点会过线一次,所以这里是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),有
4
4
4的常数.
总复杂度:
O
(
(
2
∗
m
∗
l
o
g
n
+
5
∗
n
∗
l
o
g
n
)
∗
T
)
O((2*m*logn+5*n*logn)*T)
O((2∗m∗logn+5∗n∗logn)∗T)
五、分块大法:分成根号n块,维护最大值,如果块内越界就重构(访问块内所有点,统计合法点数,重新更新最大值)好写,跑的还快。
CODE
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pf printf
inline int red()
{
int data=0;int w=1; char ch=0;
ch=getchar();
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
return data*w;
}
#define in red()
cs int N=3e4+10;
cs int long long inf=1e18;
int sum[N],n,x[N],y[N],qual[N];
#define lb(x) (x&(-x))
inline void change(int p,int k){for(;p<=n;p+=lb(p))sum[p]+=k;}
inline int query(int p){int ans=0;for(;p>=1;p-=lb(p))ans+=sum[p];return ans; }
inline void check(int u);
struct tre{
#define lc (p<<1)
#define rc ((p<<1)|1)
long long mx[N<<2];
int bord,kd,lazy[N<<2],kd2;
bool flag[N];
inline void pushup(int p){ mx[p]=max(mx[lc],mx[rc]);}
inline void pushnow(int p,int dlt){
lazy[p]+=dlt;
mx[p]+=dlt;
}
inline void pushdown(int p){
if(lazy[p])pushnow(lc,lazy[p]),pushnow(rc,lazy[p]);
lazy[p]=0;
}
inline void build(int p,int l,int r){
lazy[p]=0;
if(l==r){
int vl=kd? y[l] : x[l];
mx[p]=vl;
flag[l]=kd2?mx[p]<=bord:mx[p]<bord;
return;
}
int mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(p);
}
inline void change(int p,int l,int r,int ql,int qr,int d){
if(ql<=l&&r<=qr&&((kd2&&mx[p]+d<=bord)||(!kd2&&mx[p]+d<bord))){
pushnow(p,d);
return;
}
if(l==r){
pushnow(p,d);
flag[l]=0;
if(qual[l]^(-1))check(l);
mx[p]=-inf;
return;
}
pushdown(p);
int mid=(l+r)>>1;
if(ql<=mid)change(lc,l,mid,ql,qr,d);
if(qr>mid)change(rc,mid+1,r,ql,qr,d);
pushup(p);
}
inline void init(int _bord,int _kd,int _kd2){
bord=_bord;kd=_kd;kd2=_kd2;
}
}tr[4];
inline void check(int u){
bool f=(!tr[0].flag[u]&&tr[1].flag[u]&&!tr[2].flag[u]&&tr[3].flag[u]);
if(!qual[u]&&f)change(u,1);
if(qual[u]&&!f)change(u,-1);
if(!tr[1].flag[u]||!tr[3].flag[u])qual[u]=-1;
else qual[u]=f;
}
signed main(){
int t;t=in;
while(t--){
n=in;
int x_1,x_2,y_1,y_2;
x_1=in;y_1=in;x_2=in;y_2=in;
for(int i=1;i<=n;++i)x[i]=in,y[i]=in;
tr[0].init(x_1,0,0);tr[1].init(x_2,0,1);
tr[2].init(y_1,1,0);tr[3].init(y_2,1,1);
memset(sum,0,sizeof sum);
memset(qual,0,sizeof qual);
for(int i=0;i<4;++i)tr[i].build(1,1,n);
for(int i=1;i<=n;++i)check(i);
int m=in;
while(m--){
int f=in;
int l=in,r=in,d;
if(f==1){
d=in;
tr[1].change(1,1,n,l,r,d);
tr[0].change(1,1,n,l,r,d);
}
if(f==2){
d=in;
tr[3].change(1,1,n,l,r,d);
tr[2].change(1,1,n,l,r,d);
}
if(f==3){
pf("%d\n",query(r)-query(l-1));
}
}
}
return 0;
}