1. 程式人生 > 其它 >常用演算法題錦——線段樹

常用演算法題錦——線段樹

線段樹

最好的寶石

題目:

單值修改,區間查詢,維護資訊:最大值和最大值的個數

題目描述 
牛牛有n個寶石,第i個寶石的價值是w[i].
有m個操作,操作分為兩種型別
− Change   x  y   把第x個寶石的價值改成 y 
− Ask          l   r   詢問區間[l,r]內寶石的最大價值,和最大價值的寶石有多少個。
輸入描述:
第一行兩個整數 n , m (1 ≤ n,m ≤ 2e5)
第二行有n個整數 w[i]  (0 ≤ w[i] ≤ 1e9)
接下來m行,每行代表一個操作。具體見題目描述。
輸出描述:
每次詢問輸出一行,每行兩個整數 val  cnt,val代表所有寶石中的最大價值,cnt代表價值最大的寶石有多少個。
示例1
輸入
複製
5 3
2 4 3 6 8
Ask 1 5
Change 2 10
Ask 1 3
輸出
複製
8 1
10 1  

程式碼:

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n, m;
int w[N];
struct Node{
  int l, r;
  int mx, cnt;
}tr[N * 4];
struct Seg_Tree{
  void pushup(Node &c, Node &a, Node &b)
  {
    if (a.mx == b.mx) c.cnt = a.cnt + b.cnt;
    else if (a.mx > b.mx) c.cnt = a.cnt;
    else c.cnt = b.cnt;
    c.mx = max(a.mx, b.mx);
  }
  void pushup(int u)
  {
    pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
  }
  void build(int u, int l, int r)
  {
    if (l == r)
    {
      tr[u] = {l, r, w[l], 1};
      return;
    }
    tr[u] = {l, r};
    int mid = l + r >> 1;
    build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r);
    pushup(u);
  }
  void change(int u, int x, int c)
  {
    if  (tr[u].l == x && tr[u].r == x)
    {
      tr[u] = {x, x, c, 1};
      return;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if (x <= mid) change(u << 1, x, c);
    if (x > mid) change(u << 1 | 1, x, c);
    pushup(u);
  }
  Node query(int u, int l, int r)
  {
    if (tr[u].l >= l && tr[u].r <= r) return tr[u];
    int mid = tr[u].l + tr[u].r >> 1;
    if (r <= mid) return query(u << 1, l, r);
    else if (l > mid) return query(u << 1 | 1, l, r);
    else
    {
      Node left = query(u << 1, l, r);
      Node right = query(u << 1 | 1, l, r);
      Node ans;
      pushup(ans, left, right);
      return ans;
    }
  }
}t;
int main(void)
{
  cin >> n >> m;
  for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
  t.build(1, 1, n);
  char op[10];
  int l, r;
  while (m -- )
  {
    scanf("%s", op);
    scanf("%d%d", &l, &r);
    if (*op == 'C')
    {
      t.change(1, l, r);
    }
    else
    {
      Node x = t.query(1, l, r);
      printf("%d %d\n", x.mx, x.cnt);
    }
  }
  return 0;
}