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

来源:互联网 发布:java网络高级编程 编辑:程序博客网 时间:2024/04/30 16:55

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的最大值及位置,<=x2的最大值及位置,当前区间答案。。。
打了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;}
0 1
原创粉丝点击