poj 2464 Brownie Points II(扫描线)
题目链接:poj 2464 Brownie Points II
题意:
题意很迷啊。
有一些点,Stan选择某个点,经过这个点画一条竖线,Ollie选择一个经过这条直接的点画了条横线。
Stan选一,三象限的点,Ollie选二、四象限的点。
Stan的策略是,自己画一条竖线之后,Ollie有很多种选择,在所有选择中,Stan能获得数目的最小值的最大值,而Ollie的选择便 是让自己越多越好。
题解:
下面是cxlove dalao的题解:
首先对于某个方向离散化,我是按x排序,将y离散化。
建立两个树状数组,表示竖线左边的点个数,右边的点个数
然后按x递增扫描一遍,预先先把所有点插入到右树中。
然后逐步更新左树和右树。
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 #define F(i,a,b) for(int i=a;i<=b;++i) 6 using namespace std; 7 8 const int N=2e5+7,inf=1e9; 9 int n,hsh[N],h_ed,val[N],C1[N],C2[N],ret; 10 pair<int,int>a[N]; 11 vector<int>ans; 12 13 void add(int *C,int x,int v){while(x<=h_ed)C[x]+=v,x+=x&-x;} 14 int ask(int *C,int x){int an=0;while(x)an+=C[x],x-=x&-x;return an;} 15 16 int main() 17 { 18 while(scanf("%d",&n),n) 19 { 20 ans.clear(),ret=-1; 21 F(i,1,n) 22 { 23 scanf("%d%d",&a[i].first,&a[i].second); 24 hsh[i]=a[i].second; 25 } 26 sort(hsh+1,hsh+1+n),h_ed=unique(hsh+1,hsh+1+n)-hsh-1; 27 F(i,1,n)a[i].second=lower_bound(hsh+1,hsh+1+h_ed,a[i].second)-hsh; 28 memset(C1,0,sizeof(C1)),memset(C2,0,sizeof(C2)); 29 sort(a+1,a+1+n); 30 F(i,1,n)add(C2,a[i].second,1); 31 int st=1; 32 F(i,1,n)if(i==n||a[i+1].first!=a[i].first) 33 { 34 int aa=-1,bb=-1; 35 F(j,st,i)add(C2,a[j].second,-1); 36 F(j,st,i) 37 { 38 int y=a[j].second; 39 int ta=ask(C1,y-1)+ask(C2,h_ed)-ask(C2,y); 40 int tb=ask(C1,h_ed)-ask(C1,y)+ask(C2,y-1); 41 if(tb==bb)aa=min(aa,ta); 42 else if(tb>bb)bb=tb,aa=ta; 43 } 44 if(aa>ret)ret=aa,ans.clear(); 45 if(aa==ret)ans.push_back(bb); 46 F(j,st,i)add(C1,a[j].second,1); 47 st=i+1; 48 } 49 sort(ans.begin(),ans.end()); 50 ans.erase(unique(ans.begin(),ans.end()),ans.end()); 51 printf("Stan: %d; Ollie:",ret); 52 for(int i=0;i<ans.size();i++) 53 printf(" %d",ans[i]); 54 puts(";"); 55 } 56 return 0; 57 }