当前位置: 代码迷 >> 综合 >> poj 2464 Brownie Points II 树状数组
  详细解决方案

poj 2464 Brownie Points II 树状数组

热度:20   发布时间:2024-01-19 06:20:18.0

题意:

给Stan个点,玩家Stan先经过某个点画一条竖线,玩家Ollie再经过这条线上的某一点画一条竖线,这样将整个区域分为4个区域,左上和右下里的点是Stan的得分,左下和右上是Ollie的得分,问Stan最多能得多少分和在保证Stan的最高分的情况下Ollie能得的最高分是多少.注意Stan选择一条竖线后Ollie要站在有利于自己的情况下考虑。

分析:

这题的本质是在足够快的时间内对每个点算出:如果这个点最为最终将平面分成4份的点,两人的得分情况是什么。树状数组可以完成动态求和(动态求某个区间内元素数量),注意可以动态,所以可以通过控制访问点的顺序达到不同目的。

代码:

//poj 2464 
//sepNINE
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int maxN=200024;
map<int,int> myMap;
struct BIT
{int c[maxN],n;BIT(){}BIT(int n0){clear(),n=n0;}	void clear(){memset(c,0,sizeof(c));}int lowbit(int x){return x&(x^(x-1));}void modify(int i,int d){while(i<=n){c[i]+=d;i+=lowbit(i);}}int q(int i){int sum;for(sum=0;i>0;i-=lowbit(i))sum+=c[i];return sum;}
}myBIT;
struct Point 
{int x,y;	
}p[maxN];
int cmp(Point a,Point b)
{return a.y<b.y;
}int A[maxN],B[maxN],C[maxN],D[maxN],ans[maxN],tmp[maxN];
int firstByPoint[maxN],secondByPoint[maxN];
int firstByLine[maxN],secondByLine[maxN];
int cmp1(int a,int b)
{return a<b;
}int main()
{int n;while(scanf("%d",&n)==1&&n){myMap.clear();int i,x=0;for(i=1;i<=n;++i){scanf("%d%d",&p[i].x,&p[i].y);if(myMap[p[i].x]==0)myMap[p[i].x]=++x;}map<int,int>::iterator iter;for(iter=myMap.begin(),i=1;iter!=myMap.end();++iter,++i)iter->second=i;sort(p+1,p+1+n,cmp);myBIT.n=x;myBIT.clear();int num=0;for(i=1;i<=n;++i){//printf("deal: %d %d\n",p[i].x,p[i].y);int t=myMap[p[i].x],curY;if(i==1||p[i].y!=curY){curY=p[i].y;for(int j=0;j<num;++j)myBIT.modify(tmp[j],1);num=0;C[i]=myBIT.q(t-1);D[i]=myBIT.q(x)-myBIT.q(t);	}else{C[i]=myBIT.q(t-1);D[i]=myBIT.q(x)-myBIT.q(t);	}//printf("ans C%d D %d\n",C[i],D[i]);//printf("\n");tmp[num++]=t;}myBIT.clear();num=0;for(i=n;i>=1;--i){int t=myMap[p[i].x],curY;	if(i==n||p[i].y!=curY){curY=p[i].y;for(int j=0;j<num;++j)myBIT.modify(tmp[j],1);A[i]=myBIT.q(t-1);B[i]=myBIT.q(x)-myBIT.q(t);		num=0;}else{A[i]=myBIT.q(t-1);B[i]=myBIT.q(x)-myBIT.q(t);						}tmp[num++]=t;}		for(i=1;i<=n;++i){firstByPoint[i]=B[i]+C[i];secondByPoint[i]=A[i]+D[i];}for(i=1;i<=x;++i)secondByLine[i]=-1;for(i=1;i<=n;++i){int t=myMap[p[i].x];if(secondByPoint[i]>secondByLine[t]){secondByLine[t]=secondByPoint[i];	firstByLine[t]=firstByPoint[i];}else if(secondByPoint[i]==secondByLine[t]){firstByLine[t]=min(firstByLine[t],firstByPoint[i]);}		}int maxx=-1;for(i=1;i<=x;++i)maxx=max(maxx,firstByLine[i]);	int cnt=0;for(i=1;i<=x;++i)if(firstByLine[i]==maxx)ans[++cnt]=secondByLine[i];printf("Stan: %d; Ollie:",maxx);sort(ans+1,ans+1+cnt,cmp1);ans[0]=-1;for(i=1;i<=cnt;++i)if(ans[i]!=ans[i-1])printf(" %d",ans[i]);printf(";\n");	}return 0;	
}