poj 2482 Stars in Your Window 线段树

来源:互联网 发布:大津算法 matlab 编辑:程序博客网 时间:2024/06/05 21:22
前面几段的描述是一个上等的情书,非常感人,值得一看,哈哈!!
题目意思:
   给你n个星星,每个星星有一个价值,用一个给定大小的矩形最多能覆盖住多少价值的星星。
    这个题目思路很巧妙:
   每个星星只能被一定范围的矩形覆盖,用一个点表示一个矩形(我用的是右上角的点),这一个星星可以影响的矩形的标记构成了一个矩形。作这样的改变,把星星的权值加到矩形中,题目就变成了求矩形最大覆盖的问题了。然后就可以用扫描线的做法,先离散化,然后对y轴建立线段树,每个矩形描述成两条边,入边和出边。入边权值为星星的价值,出边为权值的负值。然后依次插入边就可以了。
   容易错的地方,y+h,x+w会超int
               y值要去重。

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;const int maxn=11111;struct data{    long long y1,y2,x;    int l,r;    int ture;    bool operator<(const data &xx) const    {       if(x==xx.x)       return(ture<xx.ture);       return(x<xx.x);    }    int sum;}d[maxn*2];long long y[maxn*2];struct{    int l,r,sum;    long long y1,y2;    int lazy;}tr[maxn*8];int maketree(int t,int l,int r){    tr[t].l=l;    tr[t].r=r;    tr[t].sum=0;    tr[t].y1=y[l];    tr[t].y2=y[r];    tr[t].lazy=0;    if(l==r)return(0);    int mid=(l+r)/2;   maketree(t*2,l,mid);   maketree(t*2+1,mid+1,r);}int pushdown(int t){   tr[t*2].sum+=tr[t].lazy;   tr[t*2].lazy+=tr[t].lazy;   tr[t*2+1].sum+=tr[t].lazy;   tr[t*2+1].lazy+=tr[t].lazy;    tr[t].lazy=0;    return(0);}int max(int a,int b){    returna>b?a:b;}int pushup(int t){    if(t==0)return(0);   tr[t].sum=max(tr[t*2].sum,tr[t*2+1].sum);    pushup(t/2);}int modify(int t,long long y1,long long y2,int tmp){   if(tr[t].y1==y1&&tr[t].y2==y2)    {       tr[t].sum+=tmp;       tr[t].lazy+=tmp;       pushup(t/2);       return(0);    }    if(tr[t].lazy!=0)    pushdown(t);    intmid=(tr[t].l+tr[t].r)/2;   if(y2<=y[mid])   modify(t*2,y1,y2,tmp);    elseif(y[mid+1]<=y1)   modify(t*2+1,y1,y2,tmp);    else    {       modify(t*2,y1,y[mid],tmp);       modify(t*2+1,y[mid+1],y2,tmp);    }}int main(){//   freopen("in.txt","r",stdin);    long long w,h;    int n;    while(scanf("%d %lld%lld",&n,&w,&h)!=EOF)    {       memset(tr,0,sizeof(tr));       w--;h--;       for(int i=1;i<=n;i++)       {           long longx,yy;           intsum;          scanf("%lld %lld%d",&x,&yy,&sum);          d[i].x=x;          d[i].y1=yy;          d[i].y2=yy+h;          d[i].ture=0;          d[i+n].x=x+w;          d[i+n].y1=yy;          d[i+n].y2=yy+h;          d[i].sum=sum;          d[i+n].sum=-sum;          d[i+n].ture=1;          y[i]=yy;       }       sort(y+1,y+n+1);       int nn=n;       for(int i=2;i<=n;i++)       if(y[i]==y[i-1])       {          y[i-1]=y[n]+h+h;          nn--;       }       sort(y+1,y+n+1);       int j=1,m=nn;       for(int i=1;i<=nn;i++)       {          while(y[j]<y[i]+h&&j<=nn)j++;          if(j>nn||y[i]+h!=y[j])          y[++m]=y[i]+h;       }       sort(y+1,y+m+1);       sort(d+1,d+2*n+1);       maketree(1,1,m);       int ans=0;       for(int i=1;i<=2*n;i++)       {//          printf("%d\n",tr[1].sum);          modify(1,d[i].y1,d[i].y2,d[i].sum);           inttxt=tr[1].sum;          ans=ans>txt?ans:txt;       }       printf("%d\n",ans);    }    return 0;}


原创粉丝点击