线段树例题

在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <algorithm>
#define N 200005
#define ll long long
using namespace std;

int n;
ll a[N], b[N], c[N], h[N];

ll sum(int i, ll *ar) {
    ll ret = 0;
    while (i > 0) {
        ret += ar[i];
        i -= i&-i;
    }
    return ret;
}

ll query(int l, int r, ll *ar) {
    return sum(r, ar) - sum(l-1, ar);
}

void update(int i, ll x, ll *ar) {
    while (i <= n) {
        ar[i] += x;
        i += i&-i;
    }
}

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    int x;
    cin>>n;
    for (int i=1; i<=n; i++)
        cin>>x, h[x] = i;
    for (int i=1; i<=n; i++)
        cin>>x, a[i] = h[x];
    
    ll ans = 0;
    for (int i=1; i<=n; i++) {
        update(a[i], a[i], b);
        update(a[i], 1, c);
        ans += a[i]*query(1, a[i]-1, c) - query(1, a[i]-1, b);
    }
    cout<<ans<<'\n';
    
    return 0;
}

在这里插入图片描述
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll

class SparseTable
{
private:
    std::vector<std::vector<int>> mx, mi;
    std::vector<int> logTable;

public:
    // 使用数组 arr 构造 ST 表
    SparseTable(const std::vector<int> &arr)
    {
        int n = arr.size();
        int maxLog = std::log2(n) + 1;
        mx.assign(n, std::vector<int>(maxLog));
        mi.assign(n, std::vector<int>(maxLog));
        logTable.assign(n + 1, 0);

        // 预处理对数表
        for (int i = 2; i <= n; i++)
        {
            logTable[i] = logTable[i / 2] + 1;
        }

        // 初始化 ST 表
        for (int i = 0; i < n; i++)
        {
            mx[i][0] = arr[i];
            mi[i][0] = arr[i];
        }

        // 动态规划填充表
        for (int j = 1; (1 << j) <= n; j++)
        {
            for (int i = 0; i + (1 << j) <= n; i++)
            {
                mx[i][j] = std::max(mx[i][j - 1], mx[i + (1 << (j - 1))][j - 1]);
                mi[i][j] = std::min(mi[i][j - 1], mi[i + (1 << (j - 1))][j - 1]);
            }
        }
    }

    // 查询区间 [l, r] 的最大值
    int querymax(int l, int r)
    {
        int j = logTable[r - l + 1];
        return std::max(mx[l][j], mx[r - (1 << j) + 1][j]);
    }

    // 查询区间 [l, r] 的最小值
    int querymin(int l, int r)
    {
        int j = logTable[r - l + 1];
        return std::min(mi[l][j], mi[r - (1 << j) + 1][j]);
    }
};
void solve()
{
    int n, q;
    cin >> n >> q;

    vector<ll> v(n + 1);
    for (int i = 1; i <= n; ++i)
    {
        cin >> v[i];
        v[i] += v[i - 1];
    }

    SparseTable st(v);
    for (int i = 0; i < q; ++i)
    {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        ll ans = 0;
        if (b < c)
        {
            ans += v[c - 1] - v[b];
        }
        ll lv = v[b] - st.querymin(a - 1, b - 1);
        ll rv = st.querymax(c, d) - v[c - 1];
        cout << (ans + lv + rv) << '\n';
    }
}
signed main()
{
    ios_base ::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout << setiosflags(ios::fixed) << setprecision(2);
    int t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

在这里插入图片描述
在这里插入图片描述

#include <iostream>
using namespace std;

int a[1000005];
struct node {
  int val, num, lazy;
} tree[4000005];

void pushup(node &n, node &n1, node &n2) {
  if (n2.val <= n1.val) {
    n.val = n2.val;
    n.num = n2.num;
  } else {
    n.val = n1.val;
    n.num = n1.num;
  }
}

void build(int l, int r, int rt) {
  tree[rt].lazy = -1;
  if (l == r) {
    tree[rt].val = a[l];
    tree[rt].num = l;
    return;
  }
  int m = (l+r)/2;
  build(l, m, rt*2);
  build(m+1, r, rt*2+1);
  pushup(tree[rt], tree[rt*2], tree[rt*2+1]);
}

void pushdown(node &n, node &n1, node &n2) {
  n1.val = max(n1.val-n.lazy, 0);
  if (n1.lazy == -1)
    n1.lazy = n.lazy;
  else
    n1.lazy += n.lazy;
  n2.val = max(n2.val-n.lazy, 0);
  if (n2.lazy == -1)
    n2.lazy = n.lazy;
  else
    n2.lazy += n.lazy;
  n.lazy = -1;
}
// 区间更新
void update(int L, int R, int C, int l, int r, int rt) {
  if (L <= l && R >= r) {
    tree[rt].val = max(tree[rt].val-C, 0);
    if (tree[rt].lazy == -1)
      tree[rt].lazy = C;
    else
      tree[rt].lazy += C;
    return;
  }
  int m = (l+r)/2;
  if (tree[rt].lazy != -1)
    pushdown(tree[rt], tree[rt*2], tree[rt*2+1]);
  if (L <= m)
    update(L, R, C, l, m, rt*2);
  if (R > m)
    update(L, R, C, m+1, r, rt*2+1);
  pushup(tree[rt], tree[rt*2], tree[rt*2+1]);
}
// 区间查询
node query(int L, int R, int l, int r, int rt) {
  if (L <= l && R >= r)
    return tree[rt];
  int m = (l+r)/2;
  if (tree[rt].lazy != -1)
    pushdown(tree[rt], tree[rt*2], tree[rt*2+1]);
  node n, n1{}, n2{};
  if (L <= m)
    n1 = query(L, R, l, m, rt*2);
  if (R > m)
    n2 = query(L, R, m+1, r, rt*2+1);
  if (n1.num == 0)
    return n2;
  if (n2.num == 0)
    return n1;
  pushup(n, n1, n2);
  return n;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int n,k;
  cin>>n>>k;
  long long sum = 0;
  for (int i=1; i<=n; i++)
    cin>>a[i], sum += a[i];
  build(1,n,1);
  long long cnt = 0;
  int i = 1;
  while (i+k-1 <= n) {
    node n0 = query(i, i+k-1, 1,n,1);
    cnt += n0.val;
    update(i, i+k-1, n0.val, 1,n,1);
    i = n0.num+1;
  }
  cout<<sum - cnt*k + cnt<<'\n';

  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值