【HDU 5283】【JZOJ 4694】 火神的鱼

    xiaoxiao2025-08-28  25

    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

    #include<cstdio> #include<cstring> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) 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
    最新回复(0)