POJ2482 Stars in Your Window 线段树 二维转换一维 STL

来源:互联网 发布:java的命名规范 编辑:程序博客网 时间:2024/05/17 23:00

解题思路: 首先注意到最优解肯定是窗子的右上角(或其他角)在某个星星位置处(这里的在是模糊的在,略微比星星的位置大一点,能包含这个星星就行)。这样就将问题变成离散空间上的问题了。然后问题关键就是将二维问题变成一维问题,先只考虑x轴方向的一维,可以想到一个星星的起到的作用是一条长度为w的线段,然后答案就是找到被最多线段覆盖的某点,就是区间最值问题了。那么再考虑y轴这一维,这一维可以认为是线段的存活时间。那么将星星分成两条线段,一个代表出生,一个代表死亡,然后按照y坐标顺序插入星星(因为在每个y坐标出要么产生一个新的线段,要么减少一个线段,都会改变已有线段树的状态),线段树的作用就是维护一个区间最值。

我觉得类似的问题有林涛论文《线段树的应用》中的例题 “蛇”,也是有类似这种二维变一维,存活时间的思想。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;#define maxn 20005#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1typedef long long ll;vector<ll> X;struct StarType{    ll x,y,c;    StarType(){}    StarType(ll x,ll y,ll c)    {        this->x=x,this->y=y,this->c=c;    }}Star[maxn];bool cmp(const StarType& a,const StarType& b){    if(a.y==b.y)        return a.c<0;    return a.y<b.y;}ll Tree[maxn<<2],Lazy[maxn<<2];void Build(){    memset(Tree,0,sizeof(Tree));    memset(Lazy,0,sizeof(Lazy));}void PushDown(int rt){    Tree[rt]+=Lazy[rt];    Lazy[rt<<1]+=Lazy[rt];    Lazy[rt<<1|1]+=Lazy[rt];    Lazy[rt]=0;}void Update(ll val,int L,int R,int l,int r,int rt){    if(L<=l&&r<=R)    {        Lazy[rt]+=val;        return ;    }    if(L>r||R<l)        return ;    if(Lazy[rt]!=0)        PushDown(rt);    int mid=(l+r)>>1;    Update(val,L,R,lson);    Update(val,L,R,rson);    Tree[rt]=max(Tree[rt<<1]+Lazy[rt<<1],Tree[rt<<1|1]+Lazy[rt<<1|1]);    return ;}  ll Query(){    return Tree[1]+Lazy[1];}  void Init(){    X.clear();    Build();}int main(){    int n,w,h,i,j,L,R,l,r;    ll ans;    while(scanf("%d %d %d",&n,&w,&h)!=EOF)    {        Init();        for(i=0;i<n;++i)        {            scanf("%lld %lld %lld",&Star[i].x,&Star[i].y,&Star[i].c);            Star[i+n].x=Star[i].x,Star[i+n].y=Star[i].y+h,Star[i+n].c=-Star[i].c;            X.push_back(Star[i].x);        }        sort(Star,Star+2*n,cmp);        X.resize(distance(X.begin(),unique(X.begin(),X.end())));        sort(X.begin(),X.end());        l=1,r=X.end()-X.begin()+1;        ans=0;        for(i=0;i<2*n;++i)        {            L=lower_bound(X.begin(),X.end(),Star[i].x)-X.begin()+1;            R=lower_bound(X.begin(),X.end(),Star[i].x+w)-X.begin();            Update(Star[i].c,L,R,l,r,1);            ans=max(ans,Query());        }        printf("%lld\n",ans);    }    return 0;}