poj 2464 Brownie Points II (扫描线)

题意:在平面直角坐标系中给你N个点,stan和ollie玩一个游戏,首先stan在竖直方向上画一条直线,该直线必须要过其中的某个点,然后ollie在水平方向上画一条直线,该直线的要求是要经过一个stan之前画过的点。 这时候平面就被分割成了四块,两个人这时候会有一个得分,stan的得分是平面上第1、3象限内的点的个数,ollie的得分是平面上第2、4象限内的点的个数,在统计的时候在所画线上的点都不计算在内。求最终stan使得自己的最差得分最高,并且输出此时ollie的得分。

        根据题目中的数据画出来的图是这样的,两边的数字分别表示的是,低于当前点y坐标的点的个数(用ol[]数组表示),高于当前点y坐标的点的个数(用st[]数组表示),分别用这两个数组建两棵线段树,表示Ollie的分数和stan的分数。处理出这样的数据后,我们把坐标以x从小到大排序,之后,每扫到一个x即是stan画下了一条竖线,这时候,Ollie画下的横线就是每个扫到的点的y坐标。

        在status 1的时候,当Ollie取的横线分别是y=-4、-3、-2时,stan的分数分别是st[-4]=9,st[-3]=7和st[-2]=5,而Ollie的分数分别是ol[-4]=1,ol[-3]=2和ol[-2]=4。(即分别在线段树里单点查询这些点的值)


当扫第x=0的时候,原来属于Ollie的3个点,即(-3,-4),(-3,-3),(-3,-3)已经是属于stan,这怎么在线段树里体现里?当这时候,当Ollie选择横线的y是大于等于-3的时候,那么(-3,-4)是点是属于stan的,那么我们就可以在stan的线段树里在区间[-3,7]里加1(这就搞定了不是?),同理处理出(-3,-3),(-3,-2),而Ollie得分的处理方式是类似的,这样的处理可以在status 1里完成,所以当我们到达status 2的时候,只需要处理(0,0)这个点,之后,那么我们在两棵线段树里分别查询y=0,即得到了在status 2时stan和Ollie的分数。

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))
const int N=200005;

struct Point
{
	int x,y;
	void get(){scanf("%d%d",&x,&y);}
	bool operator<(const Point&b)const
	{ return x mx;
map H;
int y[N],st[N],ol[N];

struct Segtree
{
	node tree[N*4];
	void down(int ind)
	{
		for(int i=0;i<2;i++)
		{
			tree[LL(ind)].flag[i]+=tree[ind].flag[i];
			tree[RR(ind)].flag[i]+=tree[ind].flag[i];
			tree[ind].flag[i]=0;
		}
	}
	void build(int lft,int rht,int ind)
	{
		tree[ind].lft=lft;	tree[ind].rht=rht;
		tree[ind].init(0,0);	
		if(lft==rht) tree[ind].init(st[lft],ol[lft]);
		else
		{
			int mid=tree[ind].mid();
			build(lft,mid,LL(ind));
			build(mid+1,rht,RR(ind));
		}
	}
	void updata(int st,int ed,int ind,int type,int valu)
	{
		int lft=tree[ind].lft,rht=tree[ind].rht;
		if(st<=lft&&rht<=ed) tree[ind].flag[type]+=valu;
		else 
		{	
			down(ind);
			int mid=tree[ind].mid();
			if(st<=mid) updata(st,ed,LL(ind),type,valu);
			if(ed> mid) updata(st,ed,RR(ind),type,valu);
		}
	}
	void query(int pos,int ind,int &mi,int &mx)
	{
		if(tree[ind].lft==tree[ind].rht) 
		{
			mi=tree[ind].flag[0];
			mx=tree[ind].flag[1];
		}
		else 
		{
			down(ind);
			int mid=tree[ind].mid();
			if(pos<=mid) return query(pos,LL(ind),mi,mx);
			if(pos> mid) return query(pos,RR(ind),mi,mx);
		}
	}
}seg;
int main()
{
	while(scanf("%d",&n),n)
	{
		H.clear(); mx.clear(); mi=m=0;

		int id1=0,id2=0;
		for(int i=0;i=n) break;
			}
			int mii=n,mxx=0;
			for(int i=id1;imi)
			{
				mi=mii;
				mx.clear(); mx.push_back(mxx);
			}
			for(int i=id1;i


你可能感兴趣的:(线段树及数据结构)