poj2464扫描线好题,树状数组解法

用树状数组解比线段树快了好多,难度也下降许多

分别用两个树状数组维护当前扫描线左侧和右侧的点,离散化y轴即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 200005
struct node{
    int x,y;
    bool operator<(const node p)const {
        return x<p.x;
    }
}p[maxn];
int y[maxn],cnt,n;
int l[maxn],r[maxn];//两个树状数组维护扫描线左边的点数,右边的点数
void add(int *bit,int x,int num){
    for(int i=x;i<=cnt+5;i+=i&-i)
        bit[i]+=num;
}
int sum(int *bit,int x){
    int res=0;
    for(int i=x;i;i-=i&-i)
        res+=bit[i];
    return res;
}

int main(){
    while(scanf("%d",&n),n){
        memset(l,0,sizeof l);
        memset(r,0,sizeof r);
        for(int i=0;i<n;i++){
            scanf("%d%d",&p[i].x,&p[i].y);
            y[i]=p[i].y;
        }
        sort(p,p+n);sort(y,y+n);
        cnt=unique(y,y+n)-y;//离散化y轴 
        for(int i=0;i<n;i++)
            add(r,lower_bound(y,y+cnt,p[i].y)-y+1,1);
        int Stan=-1,st=0;
        vector<int>Ollie;
        for(int i=1;i<=n;i++){
            if(i==n || p[i].x!=p[i-1].x){//一条竖线上的点统一处理 
                for(int j=st;j<i;j++)
                    add(r,lower_bound(y,y+cnt,p[j].y)-y+1,-1);//把这条线上的点从r数组删去 
                int stan=-1,ollie=-1;
                for(int j=st;j<i;j++){
                    int pos=lower_bound(y,y+cnt,p[j].y)-y+1;
                    int a=sum(r,cnt)-sum(r,pos)+sum(l,pos-1);
                    int b=sum(l,cnt)-sum(l,pos)+sum(r,pos-1);
                    if(b==ollie) stan=min(stan,a);//使stan得分最小化 
                    else if(b>ollie) stan=a,ollie=b;//使Ollie得分最大化 
                }
                if(stan>Stan){Stan=stan;Ollie.clear();}//stan得分更新后同时跟新Ollie得分 
                if(stan==Stan)Ollie.push_back(ollie);
                for(int j=st;j<i;j++)//最后把这条线上的点加入l数组 
                    add(l,lower_bound(y,y+cnt,p[j].y)-y+1,1);
                st=i;
            }
        }
        printf("Stan: %d; Ollie:",Stan);
        sort(Ollie.begin(), Ollie.end());
        cnt=unique(Ollie.begin(), Ollie.end())-Ollie.begin();
        for(int i=0;i<cnt;i++) printf(" %d",Ollie[i]);
        puts(";");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zsben991126/p/10115082.html