线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,实际应用时一般还要开4N的数组以免越界,因此有时需要离散化让空间压缩。
class MyCalendarTwo {
TreeMap<Integer,Integer> delta;
public MyCalendarTwo() {
delta = new TreeMap();
}
public boolean book(int start, int end) {
delta.put(start,delta.getOrDefault(start,0)+1);
delta.put(end, delta.getOrDefault(end, 0)-1);
int active = 0;
for( int d:delta.values()){
active +=d;
if(active >=3){
delta.put(start, delta.get(start)-1);
delta.put(end, delta.get(end)+1);
if(delta.get(start)==0)
delta.remove(start);
return false;
}
}
return true;
}
}
/**
* Your MyCalendarTwo object will be instantiated and called as such:
* MyCalendarTwo obj = new MyCalendarTwo();
* boolean param_1 = obj.book(start,end);
*/
class Solution {
class Node{
int ls,rs,val,add;
}
int N = (int)1e9,cnt=0;
Node[] tr= new Node[1000010];
void update(int u,int lc,int rc,int l,int r,int v){
if( l<= lc && rc<= r){
tr[u].val=v;
tr[u].add=v;
return ;
}
pushdown(u);
int mid= lc+rc >>1;
if(l<= mid) update(tr[u].ls,lc,mid,l,r,v);
if(r>mid) update(tr[u].rs,mid+1,rc,l,r,v);
pushup(u);
}
int query(int u,int lc,int rc,int l,int r){
if(l<=lc && rc<=r) return tr[u].val;
pushdown(u);
int mid = lc+rc >>1,ans=0;
if(l<=mid) ans = query(tr[u].ls,lc,mid,l,r);
if(r>mid) ans = Math.max(ans, query(tr[u].rs,mid+1,rc,l,r));
return ans;
}
void pushdown(int u){
if(tr[u]==null) tr[u]=new Node();
if(tr[u].ls ==0){
tr[u].ls=++cnt;
tr[tr[u].ls]=new Node();
}
if(tr[u].rs ==0){
tr[u].rs=++cnt;
tr[tr[u].rs]=new Node();
}
if(tr[u].add == 0) return ;
int add = tr[u].add;
tr[tr[u].ls].add = add;
tr[tr[u].rs].add = add;
tr[tr[u].ls].val = add;
tr[tr[u].rs].val = add;
tr[u].add=0;
}
void pushup(int u){
tr[u].val=Math.max(tr[tr[u].ls].val,tr[tr[u].rs].val);
}
public List<Integer> fallingSquares(int[][] positions) {
List<Integer> ans = new ArrayList<>();
tr[1] = new Node();
for(int[] info:positions){
int x = info[0], h = info[1], cur = query(1,1,N,x,x+h-1);
update(1,1,N,x,x+h-1,cur+h);
ans.add(tr[1].val);
}
return ans;
}
}