zoukankan      html  css  js  c++  java
  • POJ 2464 Brownie Points II --树状数组

    题意: 有点迷。有一些点,Stan先选择某个点,经过这个点画一条竖线,Ollie选择一个经过这条直接的点画一条横线。Stan选这两条直线分成的左下和右上部分的点,Ollie选左上和右下部分的点。Stan画一条竖线之后,Ollie有很多种选择,在所有选择中,Stan能获得 “分数最小值的最大值” ,而Ollie的选择便是让自己越多越好。问最后Stan最多能得到的分数是多少,以及在这种情况下Ollie能得到的分数有多少种可能。

    解法: 因为Stan先选,然后主动权在Ollie手中,Ollie会优先让自己得到更多的分数,然后再考虑让Stan得到的分数最小。然后才能求得Stan得到的“分数最小值的最大值”。

    既然是Stan先选,那么我们最好按x从小到大排序,y坐标离散,依次处理,又因为在同一条竖线可能有很多店,所以直到坐标变化时才来同一处理那些横坐标相同的点,Ollie在这些点对应的纵坐标中做选择,使达到上述说的效果。

    由于竖线往右移,那么维护两个树状数组,一个是当前竖线右边的点的情况,一个是左边的。然后扫过去,遇到p[i].x!=p[i-1].x时,就可以处理前面的一个或多个横坐标相同的点了,然后按上述说的做就行了。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <set>
    using namespace std;
    #define N 200007
    
    struct node{
        int x,y;
    }p[N];
    int n,maxi;
    int L[N],R[N],a[N],b[N];
    int lowbit(int x) { return x&-x; }
    int cmp1(node ka,node kb) { return ka.x < kb.x; }
    int cmp2(node ka,node kb) { return ka.y < kb.y; }
    
    void modify(int *c,int x,int val)
    {
        while(x <= maxi)
            c[x] += val, x += lowbit(x);
    }
    
    int getsum(int *c,int x)
    {
        int res = 0;
        while(x > 0) { res += c[x]; x -= lowbit(x); }
        return res;
    }
    
    int main()
    {
        int i,j;
        while(scanf("%d",&n)!=EOF && n)
        {
            maxi = 0;
            for(i=1;i<=n;i++)
                scanf("%d%d",&p[i].x,&p[i].y);
            sort(p+1,p+n+1,cmp1);                         //....离散
            for(i=1;i<=n;i++)                           
            {
                if(p[i].x == p[i-1].x) a[i] = a[i-1];
                else a[i] = a[i-1]+1;
            }
            for(i=1;i<=n;i++) p[i].x = a[i];
            sort(p+1,p+n+1,cmp2);
            for(i=1;i<=n;i++)    
            {
                if(p[i].y == p[i-1].y) b[i] = b[i-1];
                else b[i] = b[i-1]+1;
                maxi = max(maxi,b[i]);
            }
            for(i=1;i<=n;i++) p[i].y = b[i];               //离散....
            memset(L,0,sizeof(L));
            memset(R,0,sizeof(R));
            for(i=1;i<=n;i++)
                modify(R,p[i].y,1);
            int Stan = -1,ollie,stan,start = 1;
            sort(p+1,p+n+1,cmp1);
            p[n+1].x = -1,p[n+1].y = -1;
            set<int> Ollie;
            for(i=2;i<=n+1;i++)
            {
                if(p[i].x == p[i-1].x) continue;
                stan = ollie = -1;
                for(j=start;j<i;j++)
                    modify(R,p[j].y,-1);
                for(j=start;j<i;j++)
                {
                    int pos = p[j].y;
                    int STAN = getsum(R,maxi)-getsum(R,pos)+getsum(L,pos-1);   //右上+左下
                    int OLLIE = getsum(L,maxi)-getsum(L,pos)+getsum(R,pos-1);  //左上+右下
                    if(OLLIE == ollie) stan = min(stan,STAN);     //在保证Ollie取最多的情况下让Stan得分最少
                    else if(OLLIE > ollie) stan = STAN, ollie = OLLIE;
                }
                if(stan > Stan) Stan = stan, Ollie.clear(), Ollie.insert(ollie);
                else if(stan == Stan) Ollie.insert(ollie);
                for(j=start;j<i;j++)
                    modify(L,p[j].y,1);
                start = i;
            }
            printf("Stan: %d; Ollie:",Stan);
            for(set<int>::iterator it=Ollie.begin();it!=Ollie.end();it++)
                printf(" %d",*it);
            printf(";
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Zend Framework 2.1.5 中根据服务器的环境配置调用数据库等的不同配置
    在基于 Eclipse 的 IDE 中安装和使用 Emmet(ZenCoding)
    【翻译】Emmet(Zen Coding)官方文档 之六 自定义 Emmet
    【翻译】Emmet(Zen Coding)官方文档 之二 缩写
    【翻译】Emmet(Zen Coding)官方文档 之七 一览表
    【翻译】Emmet(Zen Coding)官方文档 之三 CSS 缩写
    【翻译】Emmet(Zen Coding)官方文档 之四 动作
    【翻译】Emmet(Zen Coding)官方文档 之一 web 编程的必备工具
    Zend Framework 2 时区设置警告问题的解决
    【翻译】Emmet (Zen Coding) 元素类型
  • 原文地址:https://www.cnblogs.com/whatbeg/p/4060660.html
Copyright © 2011-2022 走看看