hdu 1156

主题思路树状数组

对线段按x坐标进行排序,从小到大依次遍历,最初开始时把所有点都加入到r边的树状数组中。随着遍历,删去已经遍历过的x坐标的点,并把这些点加入到左边的树状数组中。
需要对树状数组进行统计,以及进行更改。这也是为什么用树状数组。

参考博客:http://www.cnblogs.com/Stomach-ache/p/3871751.html

AC 代码

#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn=200005;

int l[maxn],r[maxn];

struct Line{

    int x;
    int y;

};

bool cmp(Line a,Line b){
    return a.x<b.x;
}

Line line[maxn];
int y[maxn];

int n,w;
//BIT (Binary Indexed Tree)

int lowbit(int x){
    return x&(-x);
}

void update(int c[],int i,int x){

    while(i<=w){

        c[i]+=x;
        i+=lowbit(i);
    }
}
int sum(int c[],int i){

    int ans=0;
    while(i!=0){

        ans+=c[i];
        i-=lowbit(i);
    }

    return ans;
}


int main()
{

    while(scanf("%d",&n)&&n!=0){

        for(int i=0;i<n;i++){
         scanf("%d%d",&line[i].x,&line[i].y);
         y[i]=line[i].y;

        }

        //
        sort(y,y+n);

        //the number unique set

        w=unique(y,y+n)-y;

        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));

        // add all point in r at first


     //sort line by x-ray
       // sort(line,line+n,cmp);
        sort(line,line+n,cmp);

        for(int i=0;i<n;i++){
            update(r,lower_bound(y,y+w,line[i].y)+1-y,1);
        }

        int Stan=-1;
        int st=0;

        vector<int> Ollie;
        for(int i=1;i<=n;i++){

            if(i==n||line[i].x!=line[i-1].x){

                // delete element where x=line[i-1].x

                for(int j=st;j<i;j++) update(r,lower_bound(y,y+w,line[j].y)+1-y,-1);

                // search  for each y
                int stan=-1,ollie=-1;


                for(int j=st;j<i;j++){

                    int f=lower_bound(y,y+w,line[j].y)+1-y;

                    int s=sum(l,f-1)+sum(r,w)-sum(r,f);  // bottem-left +  top-right

                    int o=sum(l,w)-sum(l,f)+sum(r,f-1);

                    if(o>ollie){

                        stan=s;
                        ollie=o;
                    }else if(o==ollie){

                        stan=stan<s?stan:s;
                    }
                }

                //update Stan
                if(stan>Stan){

                    Stan=stan;
                    Ollie.clear();
                    Ollie.push_back(ollie);
                }else if(stan==Stan){

                    Ollie.push_back(ollie);
                }

                // add left of i to l
                for(int j=st;j<i;j++){

                    update(l,lower_bound(y,y+w,line[j].y)+1-y,1);
                }
                st=i;
            }
        }

        //

        sort(Ollie.begin(),Ollie.end());
        int len=unique(Ollie.begin(),Ollie.end())-Ollie.begin();

        printf("Stan: %d; Ollie:",Stan);
        for(int i=0;i<len;i++)printf(" %d",Ollie[i]);
        printf(";\n");
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值