POJ - 2482:Stars in Your Window (扫描线 )

题意:二维平面上给你N颗星,给出星星的坐标,亮度; 然后给你一个W*H的窗口,问你最大的亮度和。

思路:扫描线,假设有一个inf*H的窗口,按照y排序,那么就把H范围内的星星放入了这个窗口(单调队列实现),现在就成了华东窗口问题,在一维数组里面找长度为W的窗口的最大和,但是现在带修改,单点修改,固定区间查询,怎么做呢? 和学生讨论了一下,常规的很难实现。 我们需要转化一下,把单点修改转化为区间修改,然后单点查询最大值。    如果x处插入L,则[x,Rx]区间加x。 ans=max(mx[1]);

(可以出一道,待修改的滑动窗口问题。

#include<iostream>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=40010;
struct in{
    int x,y,l;
    bool friend operator <(in w,in v){
        return w.y<v.y;
    }
}s[maxn];
int ans,W,H,lazy[maxn],mx[maxn];
int b[maxn],tot,p[maxn];
void pushdown(int Now)
{
    if(!lazy[Now]) return ;
    lazy[Now<<1]+=lazy[Now]; lazy[Now<<1|1]+=lazy[Now];
    mx[Now<<1]+=lazy[Now]; mx[Now<<1|1]+=lazy[Now];
    lazy[Now]=0;
}
void add(int Now,int L,int R,int l,int r,int val)
{
    if(l<=L&&r>=R){
        mx[Now]+=val;
        lazy[Now]+=val;
        return ;
    }
    pushdown(Now); int Mid=(L+R)>>1;
    if(l<=Mid) add(Now<<1,L,Mid,l,r,val);
    if(r>Mid) add(Now<<1|1,Mid+1,R,l,r,val);
    mx[Now]=max(mx[Now<<1],mx[Now<<1|1]);
}
int main()
{
    int T,N;
    while(~scanf("%d%d%d",&N,&W,&H)){
        ans=0; tot=0;
        rep(i,1,N) scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].l);
        sort(s+1,s+N+1);
        rep(i,1,N<<2) lazy[i]=mx[i]=0;
        rep(i,1,N) b[++tot]=s[i].x;
        sort(b+1,b+N+1);
        tot=unique(b+1,b+N+1)-(b+1);
        rep(i,1,N) s[i].x=lower_bound(b+1,b+tot+1,s[i].x)-b;
        int R=1;
        rep(i,1,tot) {
            while(R+1<=tot&&b[R+1]-b[i]+1<=W) R++;
            p[i]=R;
        }
        for(int i=1,j=1;i<=N;i++){
            add(1,1,tot,s[i].x,p[s[i].x],s[i].l);
            while(j<=i&&s[i].y-s[j].y+1>H) {
                add(1,1,tot,s[j].x,p[s[j].x],-s[j].l);
                j++;
            }
            ans=max(ans,mx[1]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hua-dong/p/11208660.html