POJ - 2464 Brownie Points II 【树状数组 + 离散化】【好题】

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

题意
在一个二维坐标系上 给出一些点
Stan 先画一条过一点的水平线
Odd 再画一条 过Stan那条水平线上的任一点的垂直线
这两条线将坐标系分成了四个区域
Stan的得分为右上角区域的点数+左下角区域的点数
Ollie的得分为左上角区域的点数+右下角区域的点数
线上的点 不归任何人所有

两人都采用最优策略使得自己的点数最大

最后输出 Stan的最大点数 以及在Stan 这个最大点数的情况下,Ollie能够获得的最大点数

思路

首先可以想到,如果一个对应的x坐标那条垂直线上,只有一个点的话,那么对于那个点的情况,如果Stan选了那个点划线,那么Ollie 就没有选择

如果有多个点,Ollie 会选择 使得自己分最高,或者有多个分最高的情况会选择Stan 分最低的划线

处理的话,,可以先对x排序,然后插入y 就是控制变量法 ,这样就可以得到一边的数量

比如第一次,按x从小到大 过去,,可以得到左半边的数量

然后右半边 只要从大到小 再来一次 合并一下答案就可以

然后没有给出x 和 y 的坐标范围 ,但是点数只有200000 ,只要离散化一下就可以

有一些坑点 注意一下就可以

AC代码

#pragma comment(linker, "/STACK:102400000,102400000")

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <set>
#include <list>
#include <bitset>
#include <assert.h>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <limits>
//#include <xfunctional>   // greater less
//#include <unordered_map>
//#include <unordered_set>

using namespace std; 

namespace Dup4
{
    typedef long long ll;
    typedef long double ld;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair <int, int> pii;
    typedef pair <ll, ll> pll;
    typedef pair <ll, int> pli;
    typedef vector <int> vi;
    typedef vector <ll> vll;
    typedef vector < vi > vvi;

    #define fi first
    #define se second
    #define pb push_back
    #define gc getchar
    #define pc putchar
    #define p32 pc(' ')
    #define p10 pc('\n')
    #define L(on) ((on)<<1)
    #define R(on) (L(on) | 1)
    //#define gcd(a,b) __gcd(a,b)
    #define lowbit(x) ((x)&(-x))
    #define mkp(a, b) make_pair(a, b)
    #define all(x) x.begin(), x.end()
    #define rall(x) x.rbegin(), x.rend()
    #define CLR(a, b) memset(a, (b), sizeof(a));
    #define random(a,b) ((a)+rand()%((b)-(a)+1))
    #define syn_close ios::sync_with_stdio(false); cin.tie(0);

    //__builtin_popcount(i) // 返回一个数中二进制形式中1的个数

    inline int read()
    {
        int x = 0, f = 1; char c = gc();
        for (; !isdigit(c); c = gc()) f ^= (c == '-');
        for (; isdigit(c); c = gc()) x = x * 10 + (c - '0');
        return x * (f ? 1 : -1);
    }

    template <typename T>
    inline void read(T &x)
    {
        x = 0; int f = 1; char c = gc();
        for (; !isdigit(c); c = gc()) f ^= (c == '-');
        for (; isdigit(c); c = gc()) x = x * 10 + (c - '0');
        x *= f ? 1 : -1;
    }

    template <typename T>
    inline void write(T x)
    {
        if (!x) { pc(48); return; }
        if (x < 0) x = -x, pc('-');
        int bit[20], i, p = 0;
        for (; x; x /= 10) bit[++p] = x % 10;
        for (i = p; i; --i) pc(bit[i] + 48);
    }

    //仅限于正整数读入

    inline char nc()
    {
        static char buf[100000], *i = buf, *j = buf;
        return i == j && (j = (i = buf) + fread(buf, 1, 100000, stdin), i == j) ? EOF : *i++;
    }

    template <typename T>
    inline void _read(T &sum)
    {
        char ch = nc(); sum = 0;
        while (!(ch >= '0' && ch <= '9')) ch = nc();
        while (ch >= '0' && ch <= '9') sum = sum * 10 + ch - 48, ch = nc();
    }

    template <typename T>
    inline T gcd(T a, T b)
    {
        while (b ^= a ^= b ^= a %= b);
        return a;
    }

    #ifdef LOCAL
        #define gets gets_s
        #define sp system("pause");
        #define bug puts("***bug***");
    #endif

    #ifdef ONLINE_JUDGE
        #define sp
        #define bug
    #endif

    const double PI = acos(-1.0);
    const double EI = exp(1.0);
    const double eps = 1e-8;

    const int INF = 0x3f3f3f3f;
    const ll INFLL = 0x3f3f3f3f3f3f3f3fll;
}

using namespace Dup4;

namespace FastIO
{
    // 只可读入 正整数,单字符
    #define BUF_SIZE 10000005
    bool IOerror = false;
    inline char NC()
    {
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
        if (p1 == pend)
        {
            p1 = buf;
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);
            if (pend == p1)
            {
                IOerror = true;
                return -1;
            }
        }
        return *p1++;
    }

    inline bool blank(char ch)
    {
        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
    }

    inline void __read(char &x)
    {
        char ch;
        while (blank(ch = NC()));
        if (IOerror)
        {
            x = -1;
            return;
        }
        x = ch;
    }

    template <typename T>
    inline void __read(T &x)
    {
        char ch;
        while (blank(ch = NC()));
        if (IOerror)
        {
            x = -1;
            return; 
        }
        for (x = ch - '0'; isdigit(ch = NC()); x = x * 10 + ch - '0');
    }
    #undef BUF_SIZE
}

using namespace FastIO;

const int maxn = (int)2e5 + 10;
const int Maxn = (int)1e7 + 100;
const int MOD = (int)1e8 +7;

int n;
int y[maxn];

struct node
{
    int x, y;
    void scan()
    {
        x = read(), y = read();
    }
    bool operator < (const node& r) const
    {
        return x < r.x || x == r.x && y < r.y; 
    }
}cor[maxn];

bool Input()
{
    if (n = read(), n == 0) return false; 
    for (int i = 1; i <= n; i++)
        cor[i].scan(), y[i] = cor[i].y;
    sort(y + 1, y + 1 + n); 
    int pos = unique(y + 1, y + 1 + n) - y - 1;
    //cout << pos << endl;
    for (int i = 1; i <= n; i++)
    {
        int it = lower_bound(y + 1, y + 1 + pos, cor[i].y) - y;
        cor[i].y = it;
        //printf("%d%c", cor[i].y, " \n"[i == n]);
    }
    return true;
}

int a[maxn];

void add(int x)
{
    for (int i = x; i < maxn; i += lowbit(i))
        a[i] ++;
}

int sum(int x)
{
    int ans = 0;
    for (int i = x; i > 0; i -= lowbit(i))
        ans += a[i];
    return ans;
}

int ans_Stan[maxn], ans_Ollie[maxn]; 
bool vis[maxn];

void Solve()
{
    CLR(a, 0); CLR(vis, false); 
    sort(cor + 1, cor + 1 + n); 
    int tot = 0; add(cor[1].y); ans_Stan[1] = 0; ans_Ollie[1] = 0;
    for (int i = 2; i <= n; i++)
    {
        if (cor[i].x == cor[i - 1].x)
            tot++;
        else
            tot = 0;
        add(cor[i].y);
        ans_Stan[i] = sum(cor[i].y - 1) - tot;
        ans_Ollie[i] = i - sum(cor[i].y);
    }
    tot = 0; CLR(a, 0); add(cor[n].y);
    for (int i = n - 1; i >= 1; i--)
    {
        if (cor[i].x == cor[i + 1].x)
            tot++;
        else
            tot = 0;
        ans_Stan[i] += (n - i) - sum(cor[i].y) - tot;
        ans_Ollie[i] += sum(cor[i].y - 1);
        add(cor[i].y);
    }
    int index = 1, MMax = 1, Max = 0;
    //for (int i = 1; i <= n; i++)
    //  printf("%d %d %d %d\n", ans_Stan[i], ans_Ollie[i], cor[i].x, cor[i].y);
    for (int i = 2; i <= n; i++)
    {
        if (cor[i].x == cor[i - 1].x)
        {
            if (ans_Ollie[i] > ans_Ollie[MMax] || ans_Ollie[i] == ans_Ollie[MMax] && ans_Stan[i] < ans_Stan[MMax])
                MMax = i;
        }
        else 
        {
            //printf("%d %d\n", i, MMax);
            for (int j = index; j < i; j++) 
            {
                if (j == MMax)
                {
                    Max = max(Max, ans_Stan[j]);
                    continue;
                }
                //printf("%d %d\n", cor[j].x, cor[j].y - 100000);
                vis[j] = true;
            }
            index = i, MMax = i;
        }
        if (i == n)
        {
            for (int j = index; j <= n; j++)
            {
                if (j == MMax)
                {
                    Max = max(Max, ans_Stan[j]);
                    continue;
                }
                vis[j] = true;
            }
        }
    }
    //cout << Max << endl;
    vector <int> ans;
    for (int i = 1; i <= n; i++)
    {
        if (ans_Stan[i] == Max && vis[i] == false)
        {
            //printf("%d %d\n", cor[i].x, cor[i].y - 100000);
            ans.pb(ans_Ollie[i]);
        }
    }
    printf("Stan: %d; Ollie:", Max); 
    sort(all(ans)); 
    for (int i = 0, len = ans.size(); i < len; i++)
        if (i == 0 || ans[i] != ans[i - 1])
            printf(" %d", ans[i]);
    puts(";");
}

void Run()
{
    #ifdef LOCAL
        freopen("Test.in", "r", stdin);
        //freopen("1.out", "w+", stdout);
    #endif

        //t = read();  
        while (Input())
            Solve(); 

    #ifdef LOCAL
        fclose(stdin);
        //fclose(stdout);
    #endif
}

int main()
{
    Run(); 
    return 0;
}

/*

*/
posted @ 2018-07-01 11:24  Dup4  阅读(140)  评论(0编辑  收藏  举报