Description
火神最爱的就是吃鱼了,所以某一天他来到了一个池塘边捕鱼。池塘可以看成一个二维的平面,而他的渔网可以看成一个与坐标轴平行的矩形。 池塘里的鱼不停地在水中游动,可以看成一些点。有的时候会有鱼游进渔网,有的时候也会有鱼游出渔网。所以火神不知道什么时候收网才可以抓住最多的鱼,现在他寻求你的帮助。 他对池塘里的每条鱼都给予了一个标号,分别从1到n标号,n表示池塘里鱼的总数。鱼的游动可以概括为两个动作: 1 l r d : 表示标号在[l,r]这个区间内的鱼向x轴正方向游动了d个单位长度。 2 l r d:表示标号在[l,r]这个区间内的鱼向y轴正方向游动了d个单位长度。 在某些时刻火神会询问你现在有多少条他关心的鱼在渔网内(边界上的也算),请你来帮助他吧。
对于100%的数据1≤T≤10,1≤n,m≤30000,1≤l≤r≤n. 1≤d≤10^9,x1≤x2,y1≤y2。保证任意时刻所有涉及的坐标值在[−10^9,10^9]范围内。
Analysis
。。。 这题也是可以 。。。
留给我一些喘息时间
首先,我在两棵线段树打了一个build,3个query,3个modify,1个down,1个up,1个update。。。
每棵线段树里记录lazy标记,
<x1
<script type="math/tex" id="MathJax-Element-3">
<=x2
<script type="math/tex" id="MathJax-Element-4"><=x2</script>的最大值及位置,当前区间答案。。。
打了1.5h,调了3.5h。。。。
从中暴露出一个巨大有用却容易忽视的问题:
码力仍需加强,调试技术欠佳。
这道题有一个不起眼的细节却决定了此题的整个思考方向:鱼只可能往右或往上游。
又因为矩阵固定,所以鱼只要游出了矩阵就永远不可能游回来。
首先,先看x坐标。
先把区间的坐标全部加。
然后查看一下,有没有鱼游进了矩阵,有没有鱼游出了矩阵。进矩阵要满足两个坐标均位于矩阵内,若有,则更新答案,修改上面线段树记录的种种信息;出矩阵只要一个坐标出了就出了,同时可以永久地把该点删掉,修改线段树记录的种种信息。
查询直接查就可以了。
O(mlogn)
Code
using namespace std;
const
int N=
30010,INF=
2147483647;
int n,x1,y1,x2,y2,p1,p2,mp1,mp2,ans[N
*4];
struct fish
{
int x,
y;
}a[N];
struct segment
{
int mx,mn,pmx,pmn,lz;
//mn:rightest
pos lefter than x1
//mx:rightest
pos lefter than x2
}
tr[
2][N
*4];
void update(segment &a,
int z)
{
if(a.mx!=-INF) a.mx+=z;
if(a.mn!=-INF) a.mn+=z;
a.lz+=z;
}
void up(
int p,
int v)
{
if(
tr[p][v+v].mn>
tr[p][v+v+
1].mn)
tr[p][v].mn=
tr[p][v+v].mn,
tr[p][v].pmn=
tr[p][v+v].pmn;
else tr[p][v].mn=
tr[p][v+v+
1].mn,
tr[p][v].pmn=
tr[p][v+v+
1].pmn;
if(
tr[p][v+v].mx>
tr[p][v+v+
1].mx)
tr[p][v].mx=
tr[p][v+v].mx,
tr[p][v].pmx=
tr[p][v+v].pmx;
else tr[p][v].mx=
tr[p][v+v+
1].mx,
tr[p][v].pmx=
tr[p][v+v+
1].pmx;
ans[v]=ans[v+v]+ans[v+v+
1];
}
void down(
int p,
int v)
{
if(!
tr[p][v].lz)
return;
int z=
tr[p][v].lz;
update(
tr[p][v+v],z);
update(
tr[p][v+v+
1],z);
tr[p][v].lz=
0;
}
void build(
int v,
int l,
int r)
{
if(l==r)
{
tr[
0][v].pmn=
tr[
0][v].pmx=
tr[
1][v].pmn=
tr[
1][v].pmx=
tr[
0][v].lz=
tr[
1][v].lz=ans[v]=
0;
tr[
0][v].mn=
tr[
0][v].mx=
tr[
1][v].mn=
tr[
1][v].mx=-INF;
if(x1<=a[l].
x && a[l].
x<=x2 && y1<=a[l].
y && a[l].
y<=y2) ans[v]=
1;
if(a[l].
x<x1)
tr[
0][v].mn=a[l].
x,
tr[
0][v].pmn=l;
if(x1<=a[l].
x && a[l].
x<=x2)
tr[
0][v].mx=a[l].
x,
tr[
0][v].pmx=l;
if(a[l].
y<y1)
tr[
1][v].mn=a[l].
y,
tr[
1][v].pmn=l;
if(y1<=a[l].
y && a[l].
y<=y2)
tr[
1][v].mx=a[l].
y,
tr[
1][v].pmx=l;
return;
}
tr[
0][v].lz=
tr[
1][v].lz=
0;
int mid=(l+r)>>
1;
build(v+v,l,mid);
build(v+v+
1,mid+
1,r);
up(
0,v),up(
1,v);
}
void change(
int p,
int v,
int l,
int r,
int x,
int y,
int z)
{
if(l==
x && r==
y)
{
update(
tr[p][v],z);
return;
}
down(p,v);
int mid=(l+r)>>
1;
if(
y<=mid) change(p,v+v,l,mid,
x,
y,z);
else
if(
x>mid) change(p,v+v+
1,mid+
1,r,
x,
y,z);
else
change(p,v+v,l,mid,
x,mid,z),change(p,v+v+
1,mid+
1,r,mid+
1,
y,z);
up(p,v);
}
void find(
int p,
int v,
int l,
int r,
int x,
int y)
{
if(l==
x && r==
y)
{
if(
tr[p][v].mn>mp1) mp1=
tr[p][v].mn,p1=
tr[p][v].pmn;
if(
tr[p][v].mx>mp2) mp2=
tr[p][v].mx,p2=
tr[p][v].pmx;
return;
}
down(p,v);
int mid=(l+r)>>
1;
if(
y<=mid) find(p,v+v,l,mid,
x,
y);
else
if(
x>mid) find(p,v+v+
1,mid+
1,r,
x,
y);
else
find(p,v+v,l,mid,
x,mid),
find(p,v+v+
1,mid+
1,r,mid+
1,
y);
up(p,v);
}
void clear(
int p,
int v,
int l,
int r,
int x,bool bz)
{
if(l==r)
{
tr[p][v].mx=
tr[p][v].mn,
tr[p][v].pmx=
tr[p][v].pmn,
tr[p][v].mn=-INF,
tr[p][v].pmn=
0;
if(bz)
tr[p][v].mx=-INF,
tr[p][v].pmx=
0,ans[v]=
0;
return;
}
down(
0,v),down(
1,v);
int mid=(l+r)>>
1;
if(
x<=mid) clear(p,v+v,l,mid,
x,bz);
else clear(p,v+v+
1,mid+
1,r,
x,bz);
up(
0,v),up(
1,v);
}
void add(
int p,
int v,
int l,
int r,
int x)
{
if(l==r)
{
tr[p][v].mx=
tr[p][v].mn,
tr[p][v].pmx=
tr[p][v].pmn,
tr[p][v].mn=-INF,
tr[p][v].pmn=
0;
ans[v]=
1;
return;
}
down(
0,v),down(
1,v);
int mid=(l+r)>>
1;
if(
x<=mid) add(p,v+v,l,mid,
x);
else add(p,v+v+
1,mid+
1,r,
x);
up(
0,v),up(
1,v);
}
int query(
int v,
int l,
int r,
int x,
int y)
{
if(l==
x && r==
y)
return ans[v];
down(
0,v),down(
1,v);
int mid=(l+r)>>
1;
if(
y<=mid)
return query(v+v,l,mid,
x,
y);
else
if(
x>mid)
return query(v+v+
1,mid+
1,r,
x,
y);
else
return query(v+v,l,mid,
x,mid)+query(v+v+
1,mid+
1,r,mid+
1,
y);
up(
0,v),up(
1,v);
}
bool serch(
int p,
int v,
int l,
int r,
int x)
{
if(l==r)
return tr[p][v].mn==-INF &&
tr[p][v].mx!=-INF;
down(p,v);
int mid=(l+r)>>
1;
if(
x<=mid)
return serch(p,v+v,l,mid,
x);
else return serch(p,v+v+
1,mid+
1,r,
x);
up(p,v);
}
void swim(
int p,
int l,
int r,
int z)
{
change(p,
1,
1,n,l,r,z);
for(mp1=-INF,find(p,
1,
1,n,l,r);mp1>=(p?y1:x1);mp1=-INF,find(p,
1,
1,n,l,r))
{
bool ok=serch(p^
1,
1,
1,n,p1);
if(ok) add(p,
1,
1,n,p1);
else clear(p,
1,
1,n,p1,
0);
}
for(mp2=-INF,find(p,
1,
1,n,l,r);mp2>(p?y2:x2);mp2=-INF,find(p,
1,
1,n,l,r))
clear(
0,
1,
1,n,p2,
1),clear(
1,
1,
1,n,p2,
1);
}
int main()
{
int _,T,tp,l,r,z;
scanf(
"%d",&T);
while(T--)
{
scanf(
"%d %d %d %d %d",&n,&x1,&y1,&x2,&y2);
fo(i,
1,n) scanf(
"%d %d",&a[i].
x,&a[i].
y);
build(
1,
1,n);
scanf(
"%d",&
_);
fo(i,
1,
_)
{
scanf(
"%d %d %d",&tp,&l,&r);
if(tp==
1 || tp==
2)
{
scanf(
"%d",&z);
swim(tp-
1,l,r,z);
}
else
printf(
"%d\n",query(
1,
1,n,l,r));
}
}
return 0;
}
转载请注明原文地址: https://ju.6miu.com/read-1302065.html