返回介绍

solution / 0700-0799 / 0731.My Calendar II / README_EN

发布于 2024-06-17 01:03:35 字数 13626 浏览 0 评论 0 收藏 0

731. My Calendar II

中文文档

Description

You are implementing a program to use as your calendar. We can add a new event if adding the event will not cause a triple booking.

A triple booking happens when three events have some non-empty intersection (i.e., some moment is common to all the three events.).

The event can be represented as a pair of integers start and end that represents a booking on the half-open interval [start, end), the range of real numbers x such that start <= x < end.

Implement the MyCalendarTwo class:

  • MyCalendarTwo() Initializes the calendar object.
  • boolean book(int start, int end) Returns true if the event can be added to the calendar successfully without causing a triple booking. Otherwise, return false and do not add the event to the calendar.

 

Example 1:

Input
["MyCalendarTwo", "book", "book", "book", "book", "book", "book"]
[[], [10, 20], [50, 60], [10, 40], [5, 15], [5, 10], [25, 55]]
Output
[null, true, true, true, false, true, true]

Explanation
MyCalendarTwo myCalendarTwo = new MyCalendarTwo();
myCalendarTwo.book(10, 20); // return True, The event can be booked. 
myCalendarTwo.book(50, 60); // return True, The event can be booked. 
myCalendarTwo.book(10, 40); // return True, The event can be double booked. 
myCalendarTwo.book(5, 15);  // return False, The event cannot be booked, because it would result in a triple booking.
myCalendarTwo.book(5, 10); // return True, The event can be booked, as it does not use time 10 which is already double booked.
myCalendarTwo.book(25, 55); // return True, The event can be booked, as the time in [25, 40) will be double booked with the third event, the time [40, 50) will be single booked, and the time [50, 55) will be double booked with the second event.

 

Constraints:

  • 0 <= start < end <= 109
  • At most 1000 calls will be made to book.

Solutions

Solution 1

from sortedcontainers import SortedDict


class MyCalendarTwo:
  def __init__(self):
    self.sd = SortedDict()

  def book(self, start: int, end: int) -> bool:
    self.sd[start] = self.sd.get(start, 0) + 1
    self.sd[end] = self.sd.get(end, 0) - 1
    s = 0
    for v in self.sd.values():
      s += v
      if s > 2:
        self.sd[start] -= 1
        self.sd[end] += 1
        return False
    return True


# Your MyCalendarTwo object will be instantiated and called as such:
# obj = MyCalendarTwo()
# param_1 = obj.book(start,end)
class MyCalendarTwo {
  private Map<Integer, Integer> tm = new TreeMap<>();

  public MyCalendarTwo() {
  }

  public boolean book(int start, int end) {
    tm.put(start, tm.getOrDefault(start, 0) + 1);
    tm.put(end, tm.getOrDefault(end, 0) - 1);
    int s = 0;
    for (int v : tm.values()) {
      s += v;
      if (s > 2) {
        tm.put(start, tm.get(start) - 1);
        tm.put(end, tm.get(end) + 1);
        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 MyCalendarTwo {
public:
  map<int, int> m;

  MyCalendarTwo() {
  }

  bool book(int start, int end) {
    ++m[start];
    --m[end];
    int s = 0;
    for (auto& [_, v] : m) {
      s += v;
      if (s > 2) {
        --m[start];
        ++m[end];
        return false;
      }
    }
    return true;
  }
};

/**
 * Your MyCalendarTwo object will be instantiated and called as such:
 * MyCalendarTwo* obj = new MyCalendarTwo();
 * bool param_1 = obj->book(start,end);
 */
type MyCalendarTwo struct {
  *redblacktree.Tree
}

func Constructor() MyCalendarTwo {
  return MyCalendarTwo{redblacktree.NewWithIntComparator()}
}

func (this *MyCalendarTwo) Book(start int, end int) bool {
  add := func(key, val int) {
    if v, ok := this.Get(key); ok {
      this.Put(key, v.(int)+val)
    } else {
      this.Put(key, val)
    }
  }
  add(start, 1)
  add(end, -1)
  s := 0
  it := this.Iterator()
  for it.Next() {
    s += it.Value().(int)
    if s > 2 {
      add(start, -1)
      add(end, 1)
      return false
    }
  }
  return true
}

/**
 * Your MyCalendarTwo object will be instantiated and called as such:
 * obj := Constructor();
 * param_1 := obj.Book(start,end);
 */

Solution 2

class Node:
  def __init__(self, l, r):
    self.left = None
    self.right = None
    self.l = l
    self.r = r
    self.mid = (l + r) >> 1
    self.v = 0
    self.add = 0


class SegmentTree:
  def __init__(self):
    self.root = Node(1, int(1e9 + 1))

  def modify(self, l, r, v, node=None):
    if l > r:
      return
    if node is None:
      node = self.root
    if node.l >= l and node.r <= r:
      node.v += v
      node.add += v
      return
    self.pushdown(node)
    if l <= node.mid:
      self.modify(l, r, v, node.left)
    if r > node.mid:
      self.modify(l, r, v, node.right)
    self.pushup(node)

  def query(self, l, r, node=None):
    if l > r:
      return 0
    if node is None:
      node = self.root
    if node.l >= l and node.r <= r:
      return node.v
    self.pushdown(node)
    v = 0
    if l <= node.mid:
      v = max(v, self.query(l, r, node.left))
    if r > node.mid:
      v = max(v, self.query(l, r, node.right))
    return v

  def pushup(self, node):
    node.v = max(node.left.v, node.right.v)

  def pushdown(self, node):
    if node.left is None:
      node.left = Node(node.l, node.mid)
    if node.right is None:
      node.right = Node(node.mid + 1, node.r)
    if node.add:
      node.left.v += node.add
      node.right.v += node.add
      node.left.add += node.add
      node.right.add += node.add
      node.add = 0


class MyCalendarTwo:
  def __init__(self):
    self.tree = SegmentTree()

  def book(self, start: int, end: int) -> bool:
    if self.tree.query(start + 1, end) >= 2:
      return False
    self.tree.modify(start + 1, end, 1)
    return True


# Your MyCalendarTwo object will be instantiated and called as such:
# obj = MyCalendarTwo()
# param_1 = obj.book(start,end)
class Node {
  Node left;
  Node right;
  int l;
  int r;
  int mid;
  int v;
  int add;
  public Node(int l, int r) {
    this.l = l;
    this.r = r;
    this.mid = (l + r) >> 1;
  }
}

class SegmentTree {
  private Node root = new Node(1, (int) 1e9 + 1);

  public SegmentTree() {
  }

  public void modify(int l, int r, int v) {
    modify(l, r, v, root);
  }

  public void modify(int l, int r, int v, Node node) {
    if (l > r) {
      return;
    }
    if (node.l >= l && node.r <= r) {
      node.v += v;
      node.add += v;
      return;
    }
    pushdown(node);
    if (l <= node.mid) {
      modify(l, r, v, node.left);
    }
    if (r > node.mid) {
      modify(l, r, v, node.right);
    }
    pushup(node);
  }

  public int query(int l, int r) {
    return query(l, r, root);
  }

  public int query(int l, int r, Node node) {
    if (l > r) {
      return 0;
    }
    if (node.l >= l && node.r <= r) {
      return node.v;
    }
    pushdown(node);
    int v = 0;
    if (l <= node.mid) {
      v = Math.max(v, query(l, r, node.left));
    }
    if (r > node.mid) {
      v = Math.max(v, query(l, r, node.right));
    }
    return v;
  }

  public void pushup(Node node) {
    node.v = Math.max(node.left.v, node.right.v);
  }

  public void pushdown(Node node) {
    if (node.left == null) {
      node.left = new Node(node.l, node.mid);
    }
    if (node.right == null) {
      node.right = new Node(node.mid + 1, node.r);
    }
    if (node.add != 0) {
      Node left = node.left, right = node.right;
      left.add += node.add;
      right.add += node.add;
      left.v += node.add;
      right.v += node.add;
      node.add = 0;
    }
  }
}

class MyCalendarTwo {
  private SegmentTree tree = new SegmentTree();

  public MyCalendarTwo() {
  }

  public boolean book(int start, int end) {
    if (tree.query(start + 1, end) >= 2) {
      return false;
    }
    tree.modify(start + 1, end, 1);
    return true;
  }
}

/**
 * Your MyCalendarTwo object will be instantiated and called as such:
 * MyCalendarTwo obj = new MyCalendarTwo();
 * boolean param_1 = obj.book(start,end);
 */
class Node {
public:
  Node* left;
  Node* right;
  int l;
  int r;
  int mid;
  int v;
  int add;

  Node(int l, int r) {
    this->l = l;
    this->r = r;
    this->mid = (l + r) >> 1;
    this->left = this->right = nullptr;
    v = add = 0;
  }
};

class SegmentTree {
private:
  Node* root;

public:
  SegmentTree() {
    root = new Node(1, 1e9 + 1);
  }

  void modify(int l, int r, int v) {
    modify(l, r, v, root);
  }

  void modify(int l, int r, int v, Node* node) {
    if (l > r) return;
    if (node->l >= l && node->r <= r) {
      node->v += v;
      node->add += v;
      return;
    }
    pushdown(node);
    if (l <= node->mid) modify(l, r, v, node->left);
    if (r > node->mid) modify(l, r, v, node->right);
    pushup(node);
  }

  int query(int l, int r) {
    return query(l, r, root);
  }

  int query(int l, int r, Node* node) {
    if (l > r) return 0;
    if (node->l >= l && node->r <= r) return node->v;
    pushdown(node);
    int v = 0;
    if (l <= node->mid) v = max(v, query(l, r, node->left));
    if (r > node->mid) v = max(v, query(l, r, node->right));
    return v;
  }

  void pushup(Node* node) {
    node->v = max(node->left->v, node->right->v);
  }

  void pushdown(Node* node) {
    if (!node->left) node->left = new Node(node->l, node->mid);
    if (!node->right) node->right = new Node(node->mid + 1, node->r);
    if (node->add) {
      Node* left = node->left;
      Node* right = node->right;
      left->v += node->add;
      right->v += node->add;
      left->add += node->add;
      right->add += node->add;
      node->add = 0;
    }
  }
};

class MyCalendarTwo {
public:
  SegmentTree* tree = new SegmentTree();

  MyCalendarTwo() {
  }

  bool book(int start, int end) {
    if (tree->query(start + 1, end) >= 2) return false;
    tree->modify(start + 1, end, 1);
    return true;
  }
};

/**
 * Your MyCalendarTwo object will be instantiated and called as such:
 * MyCalendarTwo* obj = new MyCalendarTwo();
 * bool param_1 = obj->book(start,end);
 */
type node struct {
  left    *node
  right   *node
  l, mid, r int
  v, add  int
}

func newNode(l, r int) *node {
  return &node{
    l:   l,
    r:   r,
    mid: int(uint(l+r) >> 1),
  }
}

type segmentTree struct {
  root *node
}

func newSegmentTree() *segmentTree {
  return &segmentTree{
    root: newNode(1, 1e9+1),
  }
}

func (t *segmentTree) modify(l, r, v int, n *node) {
  if l > r {
    return
  }
  if n.l >= l && n.r <= r {
    n.v += v
    n.add += v
    return
  }
  t.pushdown(n)
  if l <= n.mid {
    t.modify(l, r, v, n.left)
  }
  if r > n.mid {
    t.modify(l, r, v, n.right)
  }
  t.pushup(n)
}

func (t *segmentTree) query(l, r int, n *node) int {
  if l > r {
    return 0
  }
  if n.l >= l && n.r <= r {
    return n.v
  }
  t.pushdown(n)
  v := 0
  if l <= n.mid {
    v = max(v, t.query(l, r, n.left))
  }
  if r > n.mid {
    v = max(v, t.query(l, r, n.right))
  }
  return v
}

func (t *segmentTree) pushup(n *node) {
  n.v = max(n.left.v, n.right.v)
}

func (t *segmentTree) pushdown(n *node) {
  if n.left == nil {
    n.left = newNode(n.l, n.mid)
  }
  if n.right == nil {
    n.right = newNode(n.mid+1, n.r)
  }
  if n.add != 0 {
    n.left.add += n.add
    n.right.add += n.add
    n.left.v += n.add
    n.right.v += n.add
    n.add = 0
  }
}

type MyCalendarTwo struct {
  tree *segmentTree
}

func Constructor() MyCalendarTwo {
  return MyCalendarTwo{newSegmentTree()}
}

func (this *MyCalendarTwo) Book(start int, end int) bool {
  if this.tree.query(start+1, end, this.tree.root) >= 2 {
    return false
  }
  this.tree.modify(start+1, end, 1, this.tree.root)
  return true
}

/**
 * Your MyCalendarTwo object will be instantiated and called as such:
 * obj := Constructor();
 * param_1 := obj.Book(start,end);
 */

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文