线段树
题目:
单值修改,区间查询,维护信息:最大值和最大值的个数
题目描述 牛牛有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;
}
原文:https://www.cnblogs.com/Iamcookieandyou/p/14998007.html