1. 程式人生 > >poj2464掃描線好題,樹狀陣列解法

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; }