poj 2464 Brownie Points II(两棵线段树——线段树区间和)

来源:互联网 发布:一体智能马桶 知乎 编辑:程序博客网 时间:2024/04/30 00:06
Brownie Points II
Time Limit: 5000MS Memory Limit: 65536KTotal Submissions: 1354 Accepted: 478

Description

Stan and Ollie play the game of Odd Brownie Points. Some brownie points are located in the plane, at integer coordinates. Stan plays first and places a vertical line in the plane. The line must go through a brownie point and may cross many (with the same x-coordinate). Then Ollie places a horizontal line that must cross a brownie point already crossed by the vertical line. 
Those lines divide the plane into four quadrants. The quadrant containing points with arbitrarily large positive coordinates is the top-right quadrant. 

The players score according to the number of brownie points in the quadrants. If a brownie point is crossed by a line, it doesn't count. Stan gets a point for each (uncrossed) brownie point in the top-right and bottom-left quadrants. Ollie gets a point for each (uncrossed) brownie point in the top-left and bottom-right quadrants. 

Stan and Ollie each try to maximize his own score. When Stan plays, he considers the responses, and chooses a line which maximizes his smallest-possible score.

Input

Input contains a number of test cases. The data of each test case appear on a sequence of input lines. The first line of each test case contains a positive odd integer 1 < n < 200000 which is the number of brownie points. Each of the following n lines contains two integers, the horizontal (x) and vertical (y) coordinates of a brownie point. No two brownie points occupy the same place. The input ends with a line containing 0 (instead of the n of a test).

Output

For each input test, print a line of output in the format shown below. The first number is the largest score which Stan can assure for himself. The remaining numbers are the possible (high) scores of Ollie, in increasing order.

Sample Input

113 23 33 43 62 -21 -30 0-3 -3-3 -2-3 -43 -70

Sample Output

Stan: 7; Ollie: 2 3;

Source

Waterloo local 2005.06.11

题目:http://poj.org/problem?id=2464

题意:这题的题意实在是虐暴我们这种E文差的菜鸟了,题意理解对就花了一晚上的,有木有= =

         就是两个人在玩一个游戏,平面上有n个点,stan要选一个点然后画一条穿过这个点的竖线,而ollie要选择一个被竖线穿过的点,画一条横线,然后平面就被分为4个象限,1,3象限的点数为stan的分数,2,4象限的点数为ollie的分数,在坐标轴上的点分数不算,现在stan想知道他一定能取得的最大得分,也就是选一条竖线,在最坏情况下得到的分数最大,而ollie则在stan选择竖线后尽量取最大,当然,stan可能有多种选法,所以ollie也就有多个得分。。。


分析:这题看清题意之后,其实方法蛮好想的,不过实现起来实在是麻烦,我的方法貌似跟别人的不大一样,不过也是大同小异,首先把y坐标离散化,然后统计大于每个y坐标的点数和小于它的点数,假设一开始stan选择x最小的竖线,那么很明显,ollie选择每个横线后两人的分数都可以统计出来(虽然有些横线选不到),只要构建两棵线段树,一棵统计stan的分数,另一棵统计ollie的分数,stan的线段树初始值就是大一y坐标的初始值,而ollie恰好相反,然后按x坐标,从小到大扫描所有点,对于一个点,先在包括它的线段上减1,然后询问,然后再在新的包括它的线段上加1,对于x坐标相同的点,要集体操作,因为这条竖线是一样的

描述不是很好,详细见代码吧= =


注意点:ollie的得分相同的就输出一次,坐标轴上的点不算,统计时候注意边界赋值


代码:

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#define ls rt<<1#define rs rt<<1|1#define lson l,m,ls#define rson m+1,r,rsusing namespace std;const int mm=222222;const int mn=mm<<2;struct point{    int x,y;}g[mm];int dly[mn][2];int y[mm],a[mm],b[mm],q[mm];void pushdown(int rt,int o){    if(dly[rt][o])    {        dly[ls][o]+=dly[rt][o];        dly[rs][o]+=dly[rt][o];        dly[rt][o]=0;    }}void build(int l,int r,int rt){    dly[rt][0]=dly[rt][1]=0;    if(l==r)    {        dly[rt][0]=b[l],dly[rt][1]=a[l];        return;    }    int m=(l+r)>>1;    build(lson);    build(rson);}void updata(int L,int R,int val,int l,int r,int rt,int o){    if(L<=y[l]&&R>=y[r])    {        dly[rt][o]+=val;        return;    }    pushdown(rt,o);    int m=(l+r)>>1;    if(L<=y[m])updata(L,R,val,lson,o);    if(R>=y[m+1])updata(L,R,val,rson,o);}int query(int x,int l,int r,int rt){    if(l==r)return rt;    pushdown(rt,0);    pushdown(rt,1);    int m=(l+r)>>1;    if(x<=y[m])return query(x,lson);    return query(x,rson);}bool cmp(point a,point b){    return a.x<b.x;}int main(){    int i,j,k,l,r,n,m,ans,maxx,minn;    while(scanf("%d",&n),n)    {        for(i=0;i<n;++i)        {            scanf("%d%d",&g[i].x,&g[i].y);            y[i]=g[i].y;        }        sort(y,y+n);        sort(g,g+n,cmp);        a[0]=0;        for(m=i=0;i<n;++i)            if(y[m]<y[i])            {                b[m]=n-i;                y[++m]=y[i];                a[m]=i;            }        b[m]=0;//初值边界没赋好导致wa了好几次        build(0,m,1);        ans=r=i=0;        while(i<n)        {            for(j=i;j<n;++j)//x坐标相同的要集体操作            {                if(g[j].y>y[0])updata(y[0],g[j].y-1,-1,0,m,1,0);                if(g[j].y<y[m])updata(g[j].y+1,y[m],-1,0,m,1,1);                if(g[j].x!=g[j+1].x)break;            }            maxx=0,minn=n;            for(k=i;k<=j;++k)            {                l=query(g[k].y,0,m,1);                minn=min(minn,dly[l][0]);                maxx=max(maxx,dly[l][1]);            }            if(minn==ans)q[r++]=maxx;            if(minn>ans)            {                ans=minn;                q[0]=maxx;                r=1;            }            for(;i<=j;++i)            {                if(g[i].y>y[0])updata(y[0],g[i].y-1,1,0,m,1,1);                if(g[i].y<y[m])updata(g[i].y+1,y[m],1,0,m,1,0);            }        }        sort(q,q+r);        for(k=i=0;i<r;++i)//相同分数就输出1次            if(q[k]<q[i])q[++k]=q[i];        printf("Stan: %d; Ollie:",ans);        for(i=0;i<=k;++i)printf(" %d",q[i]);        puts(";");    }    return 0;}

原创粉丝点击