線段樹;84柱狀圖中最大的矩形

線段樹

用處:給定數組v(n),求數組某區間[i,j]內的最大值(下標)/最小值(下標)/和

struct SegTreeNode
{
    int   le,ri;  //區間左右值,數組[le,ri],le和ri對應數組v的下標
    Node   *left;
    Node   *right;    
    //以上四個參數是必須的,下面可以根據需要增加自定義參數
    int sum;//sum=v[le]+...+v[ri]
    int max;//max=max(v[le],...,v[ri])
    int minIndex;//v[minIndex]=min(v[le],...,v[ri])
    SegTreeNode(int le,int ri) : le(le),ri(ri), left(NULL), right(NULL){}
};
SegTreeNode  *SegTreeBuild(vector<int>& v, int le ,int ri) {
    if(le>ri)return nullptr;    

    SegTreeNode   *root = new SegTreeNode(le,ri);
    
    if(le==ri){root->sum=v[le],root->max=v[le],root->minIndex=le;}//葉子節點
    else{    
        int  mid = (ri +le) >>1;
        root->left = SegTreeBuild(v, le , mid ) ;
        root->right = SegTreeBuild(v, mid+1  , ri ) ; 
        root->max=max(root->left->max,root->right->max);//更新max
        root->sum=root->left->sum+root->right->sum;//更新sum
        root->minIndex=v[root->left->minIndex]>v[root->right->minIndex]?root->right->minIndex:root->left->minIndex;//更新minIndex
    }
    return root; 
}
void   addValue(SegTreeNode  *root , int  addIndex , int  addValue)//v[addIndex]+=addValue
{
    if(root->le==root->ri&&root->le==addIndex){root->max+=addValue,root->sum+=addValue;}
    else{
        int mid=(root->le+root->ri)>>1;
        if(addIndex>=mid) addValue(root->right,addIndex,addValue);
        else addValue(root->left,addIndex,addValue);
        root->max=max(root->left->max,root->right->max);//更新max
        root->sum=root->left->sum+root->right->sum;//更新sum  
        root->minIndex=v[root->left->minIndex]>v[root->right->minIndex]?root->right->minIndex:root->left->minIndex;//更新minIndex      
    }
}
int getSum(SegTreeNode* root,int le,int ri){
    if(root->le==le&&root->root->ri==ri)return root->sum;    
    int mid=(root->le+root->ri)>>1;
    if(ri<=mid)return sum(root->left,le,ri);
    else if(le>mid)return sum(root->right,le,ri);
    else return sum(root->left,le,mid)+sum(root->right,mid+1,ri);//+ 
}
int getMax(SegTreeNode* root,int le,int ri){
    if(root->le==le&&root->root->ri==ri)return root->max;    
    int mid=(root->le+root->ri)>>1;
    if(ri<=mid)return max(root->left,le,ri);
    else if(le>mid)return max(root->right,le,ri);
    else return max(max(root->left,le,mid),max(root->right,mid+1,ri));//max(a,b)    
}
int getMinIndex(vector<int>& v,SegTreeNode* root,int le,int ri){//v
    if(root->le==le&&root->ri==ri)return root->minIndex;
    int mid=(root->le+root->ri)>>1;
    if(ri<=mid)return getMinIndex(v,root->left,le,ri);
    else if(le>mid)return getMinIndex(v,root->right,le,ri);
    else {
        int leftMinIndex=getMinIndex(v,root->left,le,mid);
        int rightMinIndex=getMinIndex(v,root->right,mid+1,ri);
        return v[leftMinIndex]>v[rightMinIndex]?rightMinIndex:leftMinIndex;//
    }
}

給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度爲 1 。

求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。

輸入: [2,1,5,6,2,3] 輸出: 10

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //分治
        if(heights.size()==0)return 0;
        if(heights.size()==1)return heights[0];
        return helper(heights,0,heights.size()-1);
    }
    int helper(vector<int>& v,int le,int ri){
        if(le>ri)return 0;
        if(le==ri)return v[le];
        int minIndex=le;
        for(int i=le+1;i<=ri;++i)
            if(v[minIndex]>v[i])
                minIndex=i;
        int maxS=minIndex==le?0:helper(v,le,minIndex-1);
        int rBig=minIndex+1;
        while(rBig<=ri&&v[rBig]==v[minIndex])
            ++rBig;
        maxS=rBig>ri?maxS:max(maxS,helper(v,rBig,ri));   
        return max(maxS,v[minIndex]*(ri-le+1)); 
    }
};

線段樹方法
 

class Solution {
public:
    struct SegTreeNode{
        int le,ri;
        SegTreeNode *left,*right;
        int minIndex;//數組下標,vec[minIndex]纔是最小值
        SegTreeNode(int le,int ri):le(le),ri(ri),left(nullptr),right(nullptr){}
    };
    int largestRectangleArea(vector<int>& heights) {
        //分治
        if(heights.size()==0)return 0;
        if(heights.size()==1)return heights[0];
        SegTreeNode* root=SegTreeBuild(heights,0,heights.size()-1);
        return getMax(heights,root,0,heights.size()-1);
    }
    SegTreeNode* SegTreeBuild(vector<int>& v,int le,int ri){
        if(le>ri)return nullptr;
        SegTreeNode* root=new SegTreeNode(le,ri);
        if(le==ri)
            root->minIndex=le;
        else{
            int mid=(le+ri)>>1;
            root->left=SegTreeBuild(v,le,mid);
            root->right=SegTreeBuild(v,mid+1,ri);
            root->minIndex=v[root->left->minIndex]>v[root->right->minIndex]?root->right->minIndex:root->left->minIndex;
        }
        return root;
    }
    int getMin(vector<int>& v,SegTreeNode* root,int le,int ri){
        if(root->le==le&&root->ri==ri)return root->minIndex;
        int mid=(root->le+root->ri)>>1;
        if(ri<=mid)return getMin(v,root->left,le,ri);
        else if(le>mid)return getMin(v,root->right,le,ri);
        else {
            int leftMinIndex=getMin(v,root->left,le,mid);
            int rightMinIndex=getMin(v,root->right,mid+1,ri);
            return v[leftMinIndex]>v[rightMinIndex]?rightMinIndex:leftMinIndex;
        }
    }
    int getMax(vector<int>& v,SegTreeNode* root,int le,int ri){
        if(le>ri)return 0;//
        if(le==ri)return v[le];
        int minIndex=getMin(v,root,le,ri);
        int mid=(le+ri)>>1;
        int leftMax=getMax(v,root,le,minIndex-1);
        int rightMax=getMax(v,root,minIndex+1,ri);
        return max((ri-le+1)*v[minIndex],max(leftMax,rightMax));
    }
};
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //遞增棧
        if(heights.size()==0)return 0;
        if(heights.size()==1)return heights[0];
        stack<int> s;
        s.push(0);
        vector<int> len(heights.size(),-1);
        int i=1;
        int maxS=0;
        while(s.size()||i<heights.size()){
            if(s.size()==0||i<heights.size()&&heights[i]>=heights[s.top()])
                s.push(i++);
            else{
                len[s.top()]+=i-s.top();
                s.pop();                
            }
        }
        s.push(heights.size()-1);
        i=heights.size()-2;
        while(s.size()||i>=0){
            if(s.size()==0||i>=0&&heights[i]>=heights[s.top()])
                s.push(i--);
            else{
                len[s.top()]+=s.top()-i;
                s.pop();                
            }
        }
        for(int j=0;j<len.size();++j)
            maxS=max(maxS,len[j]*heights[j]);
        return maxS;
    }
   
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章