luogu P1502 窗口的星星

Posted sssy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P1502 窗口的星星相关的知识,希望对你有一定的参考价值。

题目链接

P1502 窗口的星星

题解

扫描线+线段树
线段树的每一个节点处理的是左边框放在当前x-1位置时的框内星星的亮度大小
按照x坐标进行离散化,得到离散化后每一个坐标x的可影响的范围
维护扫描线,扫到可以加某颗星星就把星星加进去,扫到该出来的时候就把星星搞出来,线段树维护一下

代码

#include<cstdio> 
#include<cstring>
#include<algorithm>
 
const int maxn = 100007; 

int n,w,h;
int pou[maxn << 2],T[maxn << 2],tag[maxn << 2]; 

struct P {
    int x,y,l,k,ymax,id;  
}star[maxn << 2];  
inline bool cmp1(P a,P b) { return a.y < b.y; } 
inline bool cmp2(P a,P b) { if(a.id == b.id) return a.k < b.k; return a.id < b.id; } 
inline bool cmp3(P a,P b) { if(a.x == b.x) return a.k < b.k; return a.x < b.x;  } 
void pushdown(int x,int l,int r) { 
    if(!tag[x]) return;  
    if(l == r) { tag[x] = 0; return; } 
    int mid = l + r >> 1; 
    tag[x << 1] += tag[x]; tag[x << 1 | 1] += tag[x]; 
    T[x << 1] += tag[x];  T[x << 1 | 1]+=tag[x]; 
    tag[x] = 0; 
} 

void modify(int x,int l,int r,int tl,int tr,int val){
    pushdown(x,l,r);  
    if(tl <= l && r <= tr) { 
        tag[x] = val; T[x] += val; 
        return; 
    } 
    int mid = (l + r) >> 1; 
    if(tl <= mid) modify(x << 1,l,mid,tl,tr,val); 
    if(mid < tr) modify(x << 1 | 1,mid + 1,r,tl,tr,val); 
    T[x] = std::max(T[x << 1],T[x << 1 | 1]); 
} 
void init() { 
    memset(T,0,sizeof(T)); 
    memset(tag,0,sizeof(tag));  
    scanf("%d%d%d",&n,&w,&h);  
    for(int x,y,l,i = 1;i <= n ;++ i) {   
        scanf("%d%d%d",&x,&y,&l);  
        star[i] = (P) {x, y, l, 1};  
        star[i + n] = (P){ x + w - 1, y, -l, 2};  
        star[i + (n << 1)].y = y + h - 1;  
        star[i + (n << 1)].k = 3;   
        star[i].id = star[i + n].id = star[i + (n << 1)].id = i;  
    } 
}  
 
void solve() {  
    std::sort(star + 1,star + n * 3 + 1,cmp1);  
    int cnt = 0;  
    for(int i = 1;i <= n * 3;++ i) pou[i] = star[i].y;  
    for(int i = 1;i <= n * 3;++ i)  
        if(star[i].y == pou[i - 1]) star[i].y = star[i - 1].y;  
            else star[i].y =++ cnt;  
    std::sort(star + 1,star + n * 3 + 1,cmp2);  
    for(int i = 1;i <= n * 3;i += 3) star[i].ymax = star[i + 1].ymax = star[i + 2].y;  
    for(int i = 3;i <= n << 1;++ i)  star[i] = star[i + ((i - 1) >> 1)];  
    std::sort(star + 1,star + (n << 1) + 1,cmp3);   
    int ans = 0; 
    for(int i = 1;i <= n << 1;++ i) { 
        modify(1,0,cnt,star[i].y,star[i].ymax,star[i].l); 
        ans = std::max(ans,T[1]);
    } 
    printf("%d
",ans); 
    return ; 
} 
int main() {  
    int t; scanf("%d",&t); 
    while(t --) {  
        init();  
        solve(); 
    }  
    return 0; 
} 

以上是关于luogu P1502 窗口的星星的主要内容,如果未能解决你的问题,请参考以下文章

P1502 窗口的星星(扫描线入门第一题)

P1502 窗口的星星(扫描线)

P1502 窗口的星星 离散化+扫描线

P1502 窗口的星星 离散化+扫描线

P1502 窗口的星星 离散化+扫描线

Luogu1502 窗口的星星 (线段树扫描线)