[题解]luogu_P1502_窗口的星星(扫描线

矩形大小固定->确定矩形右上角

每个星星->能圈住每个星星的范围(常用转化

边界上不计->每个星星的范围-1

问题->若干区域,每个区域有一权值,问最大重叠的权值和

扫描线加入每个区域边界,线段树区间修改权值,维护最大值,

#include<bits/stdc++.h>
#define ll long long
#define mid (l+r>>1)
#define ls (x<<1)
#define rs (x<<1|1) 
using namespace std;
const int maxn=10009;
const int maxm=1000009;
int T,n,w,h;
struct line{
    int l,r,h;
    int f;
    bool operator <(const line &t)const{
        return h<t.h||h==t.h && f>t.f;
    }
}e[maxn<<1];int cnt;
int hsh[maxn<<1];
struct node{
    int mx;
    int tag;
}t[maxn<<3];
inline void pd(int x){
    if(t[x].tag){
        t[ls].mx+=t[x].tag;
        t[rs].mx+=t[x].tag;
        t[ls].tag+=t[x].tag;
        t[rs].tag+=t[x].tag;
        t[x].tag=0;
    }
}
inline void upd(int x){
    t[x].mx=max(t[ls].mx,t[rs].mx);
}
void change(int x,int l,int r,int L,int R,int f){
    if(L<=l && r<=R){
        t[x].tag+=f;
        t[x].mx+=f;
//        upd(x);
        return;
    }
    pd(x);
    if(L<=mid)change(ls,l,mid,L,R,f);
    if(R>mid)change(rs,mid+1,r,L,R,f);
    upd(x);
}
void solve(){
    sort(hsh+1,hsh+1+cnt);
    sort(e+1,e+1+cnt);
    int tt=unique(hsh+1,hsh+1+cnt)-hsh-1;
    int res=0;
    for(int i=1;i<=cnt;i++){
        int l=lower_bound(hsh+1,hsh+1+tt,e[i].l)-hsh;
        int r=lower_bound(hsh+1,hsh+1+tt,e[i].r)-hsh;
        change(1,1,tt,l,r,e[i].f);
        res=max(res,t[1].mx);
    }
    printf("%d\n",res);
}
int main(){
    scanf("%d",&T);
    while(T--){
        cnt=0;
        scanf("%d%d%d",&n,&w,&h);int x,y;
        memset(hsh,0,sizeof(hsh));
        memset(t,0,sizeof(t));
        for(int i=1,d;i<=n;i++){
            scanf("%d%d%d",&x,&y,&d);
            hsh[++cnt]=x;
            e[cnt].l=x;
            e[cnt].r=x+w-1;
            e[cnt].h=y;
            e[cnt].f=d;
            hsh[++cnt]=x+w-1;
            e[cnt].l=x;
            e[cnt].r=x+w-1;
            e[cnt].h=y+h-1;
            e[cnt].f=-d;
        }
        solve();
    }
}

 

posted @ 2019-09-18 09:08  羊肉汤泡煎饼  阅读(159)  评论(0编辑  收藏  举报