線段樹
用處:給定數組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;
}
};