HDU 1156 Brownie Points II

来源:互联网 发布:彩弹枪淘宝有么 编辑:程序博客网 时间:2024/05/18 00:14

题目地址
题意:给你n个点,然后你选择在坐标系选择一条垂直于x轴并经过一个点的线,然后再通过那个点做一条垂直于y轴的线,这样就形成了一个新的坐标系,第一象限和第三象限的点数为st的分数,第二象限和第四象限的点数为ol的分数,求出st最坏的情况下的最高分,并求出当时ol的分数
思路:个人对这题的理解还不是很透彻,希望有人能给我指出来,因为我们的点是按x坐标大小排序的,然后在相同x坐标,所以st画的线是一样的,所以只有ol不一样,但是我们在线段树上存的是高于该点y坐标有多少个点以及低于该点y坐标有多少个点,所以这样就把象限划分出来了。(这是我现在的理解,稍后理解清楚了一点会更新)
PS:我感觉这题还是树状数组写的比较好理解。
线段树写法:

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#define N 200010#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1e9 + 7;const double eps = 1e-9;struct node {    int flag[2];    void init(int a, int b) {        flag[0] = a;//存st        flag[1] = b;//存ol     }}sum[N << 2];//线段树主体int n, m, mi;vector<int> v;int st[N], ol[N], y[N];map<int, int>mapp;struct nope {    int x, y;    void get() { scanf("%d %d", &x, &y); }    bool operator<(const nope&b)const{        return x<b.x;    }}point[N];struct Segment__Tree {    int x, y;    void pushDown(int ans) {        for (int i = 0; i < 2; i++) {            sum[movel].flag[i] += sum[ans].flag[i];            sum[mover].flag[i] += sum[ans].flag[i];            sum[ans].flag[i] = 0;        }    }    void build(int l, int r, int ans) {        sum[ans].init(0, 0);        if (l == r) {            sum[ans].init(st[l], ol[l]);            return;        }        int mid = getMid;        build(lson);        build(rson);    }    void solve(int l, int r, int ans, int &mi,int &mx,int pos) {        if (l == r) {            mi = sum[ans].flag[0];            mx = sum[ans].flag[1];            return;        }        pushDown(ans);        int mid = getMid;        if (pos <= mid) {            return solve(lson, mi, mx, pos);        }        else {            return solve(rson, mi, mx, pos);        }    }    void updata(int l, int r, int ans, int type, int nums) {        if (l >= x&&r <= y) {            sum[ans].flag[type] += nums;            return;        }        pushDown(ans);        int mid = getMid;        if (mid >= x) {            updata(lson, type, nums);        }        if (mid < y) {            updata(rson, type, nums);        }    }};int main() {    Segment__Tree tree;    while (~scanf("%d", &n) && n) {        v.clear();        mapp.clear();        m = mi = 0;        for (int i = 0; i < n; i++) {            point[i].get();            y[i] = point[i].y;        }        sort(y, y + n);        sort(point, point + n);        mapp[y[0]] = 0;        for (int i = 0; i < n; i++) {//离散化            if (y[m] != y[i]) {                st[m] = n - i;//存高于该点y坐标有多少个点                y[++m] = y[i];                ol[m] = i;//存低于该点y坐标有多少个点                mapp[y[m]] = m;            }        }        st[m] = 0;        tree.build(0, m, 1);        int id1 = 0;        int id2 = 0;        while (id1 < n) {             id2 = id1;            while (point[id1].x == point[id2].x) {//先给x轴相同的点-1                if (point[id2].y != y[0]) {                    tree.x = 0;                    tree.y = mapp[point[id2].y] - 1;//第二象限,ol减分                    tree.updata(0, m, 1, 0, -1);                }                if (point[id2].y != y[m]) {                    tree.x = mapp[point[id2].y] + 1;//第四象限,ol减分                    tree.y = m;                    tree.updata(0, m, 1, 1, -1);                }                if (++id2 >= n) break;            }            int mii = n, mxx = 0;            for (int i = id1; i < id2; i++) {                int tmp1, tmp2;                tree.solve(0, m, 1, tmp1, tmp2, mapp[point[i].y]);//查询point[i]st,ol的得分                mii = min(mii, tmp1);//st的得分                mxx = max(mxx, tmp2);//ol的得分            }            if (mii == mi) {                v.push_back(mxx);            }            else if (mii > mi) {                mi = mii;                v.clear();                v.push_back(mxx);            }            for (int i = id1; i < id2; i++) {                if (point[i].y != y[0]) {                    tree.x = 0;                    tree.y = mapp[point[i].y] - 1;//第三象限,st加分                    tree.updata(0, m, 1, 1, 1);                }                if (point[i].y != y[m]) {                    tree.x = mapp[point[i].y] + 1;//第一象限,st加分                    tree.y = m;                    tree.updata(0, m, 1, 0, 1);                }            }            id1 = id2;        }        sort(v.begin(), v.end());        int len = unique(v.begin(), v.end()) - v.begin();        printf("Stan: %d; Ollie:", mi);        for (int i = 0; i < len; i++) printf(" %d", v[i]);        printf(";\n");    }    return 0;}
原创粉丝点击