• HDU 2795 Billboard


    线段树,保存区间最大值,从顶端下来,优先往左边走,确定位置,然后更新。

    /* ***********************************************
    Author        :Zhou Zhentao
    Email         :774388357@qq.com
    Created Time  :2015/11/21 9:45:58
    File Name     :acm.cpp
    ************************************************ */
    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
      
      
    using namespace std;  
      
    #define MAXN 200000+10
    #define INF 0x7fffffff  
      
    int A[MAXN];  
    int v[MAXN];
    int Wnow[MAXN];
    //int max;  
    //int min;  
      
    struct node  
    {  
        int left;  
        int right;  
        int max;           //维护最大值  
        int sum;          //维护区间和  
        int min;           //维护最小值  
    }Tree[MAXN<<2];  
    
    int h,w,n;
      
    void maintain(int root)         //向上调整  
    {  
        int LC = root<<1;  
        int RC = (root<<1)+1;  
        Tree[root].sum = Tree[LC].sum + Tree[RC].sum;  
        Tree[root].max = max(Tree[LC].max,Tree[RC].max);  
        Tree[root].min = min(Tree[LC].min,Tree[RC].min);  
    }  
      
    void Build(int root,int start,int end)                     //构建线段树  
    {  
        Tree[root].left = start;  
        Tree[root].right = end;  
        if(start == end)  
        {  
            Tree[root].sum = Wnow[start];  
            Tree[root].max = Wnow[start];  
            Tree[root].min = Wnow[start];  
            return;
        }  
        int mid = (start + end)>>1;  
        Build(root<<1,start,mid);  
        Build((root<<1)+1,mid+1,end);  
        maintain(root);  
    }  
      
    void update(int root,int pos,int value)                     //更新点的值  
    {  
        if(Tree[root].left == Tree[root].right && Tree[root].left == pos)  
        {  
            Tree[root].sum += value;  
            Tree[root].max += value;  
            Tree[root].min += value;  
            return;  
        }  
        int mid = (Tree[root].left + Tree[root].right)>>1;  
        if(pos <= mid)  
            update(root<<1,pos,value);  
        else  
            update((root<<1)+1,pos,value);  
        maintain(root);  
    }  
      
    int Query(int root,int start,int end)                         //查询区间和  
    {  
        if(start == Tree[root].left && Tree[root].right == end)  
        {  
            return Tree[root].sum;  
        }  
        int mid = (Tree[root].left + Tree[root].right)>>1;  
        int ret = 0;  
        if(end <= mid)  
            ret += Query(root<<1,start,end);  
        else if(start >= mid+1)  
            ret += Query((root<<1)+1,start,end);  
        else  
        {  
            ret += Query(root<<1,start,mid);  
            ret += Query((root<<1)+1,mid+1,end);  
        }  
        return ret;  
    }  
      
    int RminQ(int root,int start,int end)              //查询区间最小值  
    {  
        if(start == Tree[root].left && Tree[root].right == end)  
        {  
            return Tree[root].min;  
        }  
        int mid = (Tree[root].left + Tree[root].right)>>1;  
        int ret = INF;  
        if(end <= mid)  
            ret = min(ret,RminQ(root<<1,start,end));  
        else if(start >= mid+1)  
            ret = min(ret,RminQ((root<<1)+1,start,end));  
        else  
        {  
            int a = RminQ(root<<1,start,mid);  
            int b = RminQ((root<<1)+1,mid+1,end);  
            ret = min(a,b);  
        }  
        return ret;  
    }  
      
    int RmaxQ(int root,int start,int end)                 //查询区间最大值  
    {  
        if(start == Tree[root].left && Tree[root].right == end)  
        {  
            return Tree[root].max;  
        }  
        int mid = (Tree[root].left + Tree[root].right)>>1;  
        int ret = 0;    //modify this  
        if(end <= mid)  
            ret = max(ret,RmaxQ(root<<1,start,end));  
        else if(start >= mid+1)  
            ret = max(ret,RmaxQ((root<<1)+1,start,end));  
        else  
        {  
            int a = RmaxQ(root<<1,start,mid);  
            int b = RmaxQ((root<<1)+1,mid+1,end);  
            ret = max(a,b);  
        }  
        return ret;  
    }  
    
    
    int main()
    {
        while(~scanf("%d%d%d",&h,&w,&n))
        {
            for(int i=1;i<=n;i++) scanf("%d",&v[i]);
               for(int i=1;i<=min(h,n);i++) Wnow[i]=w;
    
            Build(1,1,min(h,n));
    
            for(int i=1;i<=n;i++)
            {
                if(Tree[1].max<v[i]) 
                {
                       printf("-1
    ");
                    continue;
                }
                int now=1;
                   while(1)
                {
                    if(Tree[now].left==Tree[now].right)
                    {
                        printf("%d
    ",Tree[now].left);
                        update(1,Tree[now].left,-v[i]);
                        break;
                    }
                    else
                    {
                        if(Tree[now<<1].max>=v[i]) now=(now<<1);
                        else now=(now<<1)+1;
                    }
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    Easy | LeetCode 108. 将有序数组转换为二叉搜索树
    Medium | LeetCode 105 | 剑指 Offer 07. 从前序与中序遍历序列构造二叉树
    Easy | LeetCode 543. 二叉树的直径
    Easy | LeetCode 235 | 剑指 Offer 68
    Easy | LeetCode 236 | 剑指 Offer 68
    Medium | LeetCode 114. 二叉树展开为链表 | 先序遍历 | 递归 | 迭代
    Medium | LeetCode 538,1038. 把二叉搜索树转换为累加树
    Medium | LeetCode 230. 二叉搜索树中第K小的元素
    Easy | 剑指 Offer 54. 二叉搜索树的第k大节点
    stl(5)vector容器
  • 原文地址:https://www.cnblogs.com/zufezzt/p/4983986.html
Copyright © 2020-2023  润新知