zoukankan      html  css  js  c++  java
  • poj 2482 Stars in Your Window 夜

    http://poj.org/problem?id=2482

    黑书的102~104有个十分类似的题,解法一样 推荐

    题目大意:

    刚开始的情书 ,十分的不错。

    给你个矩形去框星星 矩形能移不能转,边框上的星星不算,星星都是有亮度值的

    问可以得到的最大亮度值和

    思路:

    由于都是整数,比如说边框左边有星星 右边也有星星 只有左右移动一下就可以多框

    一些星星,所以我们默认 边框星星 取左不取右,取下不取上

    我们对y坐标排序,根据y建二叉树 左子树一定小于根节点 右子树一定大于根节点

    对x排序,我们用两个扫描线,使它们两者之间的星星x距离不超过w

    然后对其求最大矩形内亮度和。

    我们可以把一个点拆成两个 原来的点是x ,y,value再多加一个点 x,y+h,-value

    这样的话 两个扫描线之间的星星求矩形内点亮度和,变成了,用一个扫描线向上扫,求扫过部分的

    所用点的两度和。

    至于点的更新 和答案的更新 见代码及其注释:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    
    using namespace std;
    
    const int N=10010;
    struct node
    {
        int I;//在完全二叉树里的位置
        int x;
        unsigned int y;//y加h后会超过2^31
        int value;
    }mem[N*4];
    struct tree
    {
        int value;
        int max;
        int sum;
    }btree[N*8];
    bool cmpx(node a,node b)
    {
        return a.x<b.x;
    }
    bool cmpy(node a,node b)
    {
        if(a.y==b.y)//要把负的value排在前面
        return a.value<b.value;
        return a.y<b.y;
    }
    void build(int l,int r,int w)
    {
        int k=(l+r+1)>>1;//区间内的根节点
        mem[k].I=w;//记录在完全二叉树里的位置
        if(l<k)
        {
            build(l,k-1,2*w);
        }
        if(k<r)
        {
            build(k+1,r,2*w+1);
        }
    }
    void update(int x)
    {
        btree[x].sum=btree[x*2].sum+btree[x*2+1].sum+btree[x].value;//sum需要相加
        btree[x].max=max(max(btree[x*2].max,0),//max需要用到DP的思想
                        max(btree[x*2].sum+btree[x].value,btree[x*2].sum+btree[x].value+btree[x*2+1].max));
        if(x!=1)//不是总根节点 继续更新
        {
            update(x/2);
        }
    }
    int main()
    {
        int n,w,h;
        while(scanf("%d %d %d",&n,&w,&h)!=EOF)
        {
            for(int i=1;i<=n;++i)
            {
                scanf("%d %d %d",&mem[i].x,&mem[i].y,&mem[i].value);
            }
            for(int i=n+1;i<=2*n;++i)//一个点拆成两个点
            {
                mem[i].x=mem[i-n].x;
                mem[i].y=mem[i-n].y+h;
                mem[i].value=-mem[i-n].value;
            }
            for(int i=0;i<=4*n+1;++i)//初始化 4*n+1 中的+1很重要
            {
                btree[i].max=0;
                btree[i].value=0;
                btree[i].sum=0;
            }
            sort(mem+1,mem+2*n+1,cmpy);//按y排序
            build(1,2*n,1);//建树 实际上是找好对于的点
            sort(mem+1,mem+2*n+1,cmpx);//按x排序
            int L,R;
            L=R=1;
            int ans=0;
            while(R<=2*n)
            {
                while(R<=2*n&&mem[R].x-mem[L].x<w)//加点
                {
                    btree[mem[R].I].value=mem[R].value;
                    update(mem[R].I);
                    ++R;
                }
                ans=max(ans,btree[1].max);//加点后求最大值
                while(R<=2*n&&mem[R].x-mem[L].x>=w)//去点
                {
                    btree[mem[L].I].value=0;
                    update(mem[L].I);
                    ++L;
                }
            }
            printf("%d\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    Graphic
    GUI编程实战
    Swing 混合布局
    运算符与数据库函数
    mysq基础操作
    mysql常见问题处理
    static 与final abstract关键字
    JAVA面试
    Swing
    AWT的应用
  • 原文地址:https://www.cnblogs.com/liulangye/p/2590252.html
Copyright © 2011-2022 走看看