当前位置: 首页 > news >正文

线段树刷题记录

一、区间查询 无修改:

(一)最值问题:

1.P1816 忠诚 - 洛谷
思路:

        模板。

注意:

        无。

代码:
#include <bits/stdc++.h>#define ioscc ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
#define me(a, x) memset(a, x, sizeof a)
#define all(a) a.begin(), a.end()
#define sz(a) ((int)(a).size())
#define pb(a) push_back(a)
using namespace std;typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
const int MAX = (1ll << 31) - 1;
const int MIN = 1 << 31;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cout << a[i] << ' ';return os;
}template <class T>
istream &operator>>(istream &in, vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cin >> a[i];return in;
}/* ----------------- 有乘就强转,前缀和开ll ----------------- */int v[N];
struct Node
{int l, r;int minn;
} tr[N * 4];void pushup(int u)
{tr[u].minn = min(tr[u << 1].minn, tr[u << 1 | 1].minn);
}void build(int u, int l, int r)
{if (l == r){tr[u] = {l, r, v[l]};return;}tr[u] = {l, r};int mid = l + r >> 1;build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);pushup(u);
}int query(int u, int l, int r)
{if (tr[u].l >= l && tr[u].r <= r){return tr[u].minn;}int mid = tr[u].l + tr[u].r >> 1;int minn = MAX;if (l <= mid)minn = min(minn, query(u << 1, l, r));if (r > mid)minn = min(minn, query(u << 1 | 1, l, r));return minn;
}void solve()
{int n, m;cin >> n >> m;for (int i = 1; i <= n; ++i)cin >> v[i];build(1, 1, n);while (m--){int l, r;cin >> l >> r;cout << query(1, l, r) << ' ';}cout << endl;
}int main()
{ioscc;solve();return 0;
}
2.P1886 滑动窗口 /【模板】单调队列 - 洛谷
思路:

        模板。

注意:

        无。

代码:
#include <bits/stdc++.h>#define ioscc ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
#define me(a, x) memset(a, x, sizeof a)
#define all(a) a.begin(), a.end()
#define sz(a) ((int)(a).size())
#define pb(a) push_back(a)
using namespace std;typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
const int MAX = (1ll << 31) - 1;
const int MIN = 1 << 31;
const int MOD = 1e9 + 7;
const int N = 1e6 + 10;template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cout << a[i] << ' ';return os;
}template <class T>
istream &operator>>(istream &in, vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cin >> a[i];return in;
}/* ----------------- 有乘就强转,前缀和开ll ----------------- */int v[N];
struct Node
{int l, r;int minn, maxx;
} tr[N * 4];void pushup(int u)
{tr[u].minn = min(tr[u << 1].minn, tr[u << 1 | 1].minn);tr[u].maxx = max(tr[u << 1].maxx, tr[u << 1 | 1].maxx);
}void build(int u, int l, int r)
{if (l == r){tr[u] = {l, r, v[l], v[l]};return;}tr[u] = {l, r, 0, 0};int mid = l + r >> 1;build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);pushup(u);
}int queryMin(int u, int l, int r)
{if (tr[u].l >= l && tr[u].r <= r){return tr[u].minn;}int mid = tr[u].l + tr[u].r >> 1;int minn = MAX;if (l <= mid)minn = min(minn, queryMin(u << 1, l, r));if (r > mid)minn = min(minn, queryMin(u << 1 | 1, l, r));return minn;
}int queryMax(int u, int l, int r)
{if (tr[u].l >= l && tr[u].r <= r){return tr[u].maxx;}int mid = tr[u].l + tr[u].r >> 1;int maxx = MIN;if (l <= mid)maxx = max(maxx, queryMax(u << 1, l, r));if (r > mid)maxx = max(maxx, queryMax(u << 1 | 1, l, r));return maxx;
}void solve()
{int n, k;cin >> n >> k;for (int i = 1; i <= n; ++i)cin >> v[i];build(1, 1, n);for (int i = 1; i <= n - k + 1; ++i)cout << queryMin(1, i, i + k - 1) << ' ';cout << endl;for (int i = 1; i <= n - k + 1; ++i)cout << queryMax(1, i, i + k - 1) << ' ';cout << endl;
}int main()
{ioscc;solve();return 0;
}

二、区间查询 单点修改:

(一)区间和问题:

1.P2068 统计和 - 洛谷
思路:

        模板。

注意:

        无。

代码:
#include <bits/stdc++.h>#define ioscc ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
#define me(a, x) memset(a, x, sizeof a)
#define all(a) a.begin(), a.end()
#define sz(a) ((int)(a).size())
#define pb(a) push_back(a)
using namespace std;typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
const int MAX = (1ll << 31) - 1;
const int MIN = 1 << 31;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cout << a[i] << ' ';return os;
}template <class T>
istream &operator>>(istream &in, vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cin >> a[i];return in;
}/* ----------------- 有乘就强转,前缀和开ll ----------------- */struct Node
{int l, r;ll sum;
} tr[N * 4];void pushup(int u)
{tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}void build(int u, int l, int r)
{if (l == r){tr[u] = {l, r, 0};return;}tr[u] = {l, r, 0};int mid = l + r >> 1;build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);pushup(u);
}ll query(int u, int l, int r)
{if (tr[u].l >= l && tr[u].r <= r)return tr[u].sum;int mid = tr[u].l + tr[u].r >> 1;ll sum = 0;if (l <= mid)sum += query(u << 1, l, r);if (r > mid)sum += query(u << 1 | 1, l, r);return sum;
}void update(int u, int x, int v)
{if (tr[u].l == x && tr[u].r == x)tr[u].sum += v;else{int mid = tr[u].l + tr[u].r >> 1;if (x <= mid)update(u << 1, x, v);elseupdate(u << 1 | 1, x, v);pushup(u);}
}void solve()
{int n, m;cin >> n >> m;build(1, 1, n);while (m--){char op;int a, b;cin >> op >> a >> b;if (op == 'x')update(1, a, b);elsecout << query(1, a, b) << endl;}
}int main()
{ioscc;solve();return 0;
}
2.P2184 贪婪大陆 - 洛谷
思路:

        区间修改时使用一种类差分的思想,每次埋地雷的时候只在区间左右端点累加一次值,这样就将问题装换为了单点修改;查询时我们再使用前缀和思想统计区间 [l, r] 区间内的地雷数。具体实现就是使用线段树维护两个sum,既区间左端点的地雷和区间右端点的地雷;在查询区间 [l ,r] 时,就可以用 [1, r] 的起点数减去 [1, l] 的终点数。

注意:

        无。

代码:
#include <bits/stdc++.h>#define ioscc ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
#define me(a, x) memset(a, x, sizeof a)
#define all(a) a.begin(), a.end()
#define sz(a) ((int)(a).size())
#define pb(a) push_back(a)
#define ls u << 1
#define rs u << 1 | 1
using namespace std;typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
const int MAX = (1ll << 31) - 1;
const int MIN = 1 << 31;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cout << a[i] << ' ';return os;
}template <class T>
istream &operator>>(istream &in, vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cin >> a[i];return in;
}/* ----------------- 有乘就强转,前缀和开ll ----------------- */struct Node
{int l, r;int sum[2];
} tr[N * 4];void pushup(int u, int k)
{tr[u].sum[k] = tr[u << 1].sum[k] + tr[u << 1 | 1].sum[k];
}void build(int u, int l, int r)
{tr[u] = {l, r, 0, 0};if (l == r)return;int mid = l + r >> 1;build(u << 1, l, mid);build(u << 1 | 1, mid + 1, r);
}ll query(int u, int l, int r, int k)
{if (tr[u].l >= l && tr[u].r <= r)return tr[u].sum[k];int mid = tr[u].l + tr[u].r >> 1;ll sum = 0;if (l <= mid)sum += query(u << 1, l, r, k);if (r > mid)sum += query(u << 1 | 1, l, r, k);return sum;
}void update(int u, int x, int k)
{if (tr[u].l == tr[u].r){++tr[u].sum[k];return;}int mid = tr[u].l + tr[u].r >> 1;if (x <= mid)update(u << 1, x, k);elseupdate(u << 1 | 1, x, k);pushup(u, k);
}void solve()
{int n, m;cin >> n >> m;build(1, 1, n);while (m--){int op, l, r;cin >> op >> l >> r;if (op == 1)update(1, l, 0), update(1, r, 1);elsecout << query(1, 1, r, 0) - query(1, 1, l - 1, 1) << endl;}
}int main()
{ioscc;solve();return 0;
}

三、区间查询 区间修改:

(一)区间和问题:

1.P2357 守墓人 - 洛谷
思路:

        模板。

注意:

        开ll。

代码:
#include <bits/stdc++.h>#define ioscc ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
#define me(a, x) memset(a, x, sizeof a)
#define all(a) a.begin(), a.end()
#define sz(a) ((int)(a).size())
#define pb(a) push_back(a)
using namespace std;typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
const int MAX = (1ll << 31) - 1;
const int MIN = 1 << 31;
const int MOD = 1e9 + 7;
const int N = 2e5 + 10;template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cout << a[i] << ' ';return os;
}template <class T>
istream &operator>>(istream &in, vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cin >> a[i];return in;
}/* ----------------- 有乘就强转,前缀和开ll ----------------- */ll v[N];
struct Node
{int l, r;ll sum;ll add;
} tr[N * 4];void pushup(int u)
{tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}void pushdown(int u)
{if (tr[u].add){tr[u << 1].sum += tr[u].add * (tr[u << 1].r - tr[u << 1].l + 1);tr[u << 1 | 1].sum += tr[u].add * (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1);tr[u << 1].add += tr[u].add;tr[u << 1 | 1].add += tr[u].add;tr[u].add = 0;}
}void build(int u, int l, int r)
{if (l == r){tr[u] = {l, r, v[l], 0};return;}tr[u] = {l, r, 0, 0};int mid = l + r >> 1;build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);pushup(u);
}ll query(int u, int l, int r)
{if (tr[u].l >= l && tr[u].r <= r)return tr[u].sum;pushdown(u);int mid = tr[u].l + tr[u].r >> 1;ll sum = 0;if (l <= mid)sum += query(u << 1, l, r);if (r > mid)sum += query(u << 1 | 1, l, r);return sum;
}void update(int u, int l, int r, int v)
{if (tr[u].l >= l && tr[u].r <= r){tr[u].sum += (ll)(tr[u].r - tr[u].l + 1) * v;tr[u].add += v;return;}pushdown(u);int mid = tr[u].l + tr[u].r >> 1;if (l <= mid)update(u << 1, l, r, v);if (r > mid)update(u << 1 | 1, l, r, v);pushup(u);
}void solve()
{int n, m;cin >> n >> m;for (int i = 1; i <= n; ++i)cin >> v[i];build(1, 1, n);while (m--){int op;int l, r, v;cin >> op;if (op == 1){cin >> l >> r >> v;update(1, l, r, v);}else if (op == 2){cin >> v;update(1, 1, 1, v);}else if (op == 3){cin >> v;update(1, 1, 1, -v);}else if (op == 4){cin >> l >> r;cout << query(1, l, r) << endl;}elsecout << query(1, 1, 1) << endl;}
}int main()
{ioscc;solve();return 0;
}

(二)区间最值+区间和问题:

1.P3130 [USACO15DEC] Counting Haybale P - 洛谷
思路:

        线段树维护区间、最小值、区间和、懒标记。

注意:

        更新懒标记时也需将节点的最小值加上懒标记的值。

代码:
#include <bits/stdc++.h>#define ioscc ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
#define me(a, x) memset(a, x, sizeof a)
#define all(a) a.begin(), a.end()
#define sz(a) ((int)(a).size())
#define pb(a) push_back(a)
using namespace std;typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
const int MAX = (1ll << 31) - 1;
const int MIN = 1 << 31;
const int MOD = 1e9 + 7;
const int N = 2e5 + 10;template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cout << a[i] << ' ';return os;
}template <class T>
istream &operator>>(istream &in, vector<T> &a) noexcept
{for (int i = 0; i < sz(a) - 10; i++)std::cin >> a[i];return in;
}/* ----------------- 有乘就强转,前缀和开ll ----------------- */ull v[N];
struct Node
{int l, r;ull minn;ull sum;ull add;
} tr[N * 4];void pushup(int u)
{tr[u].minn = min(tr[u << 1].minn, tr[u << 1 | 1].minn);tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}void pushdown(int u)
{if (tr[u].add){tr[u << 1].sum += tr[u].add * (tr[u << 1].r - tr[u << 1].l + 1);tr[u << 1 | 1].sum += tr[u].add * (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1);tr[u << 1].minn += tr[u].add;tr[u << 1 | 1].minn += tr[u].add;tr[u << 1].add += tr[u].add;tr[u << 1 | 1].add += tr[u].add;tr[u].add = 0;}
}void build(int u, int l, int r)
{if (l == r){tr[u] = {l, r, v[l], v[l], 0};return;}tr[u] = {l, r, 0, 0, 0};int mid = l + r >> 1;build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);pushup(u);
}ull querySum(int u, int l, int r)
{if (tr[u].l >= l && tr[u].r <= r){return tr[u].sum;}pushdown(u);int mid = tr[u].l + tr[u].r >> 1;ull sum = 0;if (l <= mid)sum += querySum(u << 1, l, r);if (r > mid)sum += querySum(u << 1 | 1, l, r);return sum;
}ull queryMin(int u, int l, int r)
{if (tr[u].l >= l && tr[u].r <= r){return tr[u].minn;}pushdown(u);int mid = tr[u].l + tr[u].r >> 1;ull minn = MAX;if (l <= mid)minn = min(minn, queryMin(u << 1, l, r));if (r > mid)minn = min(minn, queryMin(u << 1 | 1, l, r));return minn;
}void update(int u, int l, int r, int v)
{if (tr[u].l >= l && tr[u].r <= r){tr[u].sum += (ull)(tr[u].r - tr[u].l + 1) * v;tr[u].minn += v;tr[u].add += v;return;}pushdown(u);int mid = tr[u].l + tr[u].r >> 1;if (l <= mid)update(u << 1, l, r, v);if (r > mid)update(u << 1 | 1, l, r, v);pushup(u);
}void solve()
{int n, m;cin >> n >> m;for (int i = 1; i <= n; ++i)cin >> v[i];build(1, 1, n);while (m--){char op;int a, b, c;cin >> op;if (op == 'M'){cin >> a >> b;cout << queryMin(1, a, b) << endl;}else if (op == 'P'){cin >> a >> b >> c;update(1, a, b, c);}else{cin >> a >> b;cout << querySum(1, a, b) << endl;}}
}int main()
{ioscc;solve();return 0;
}

相关文章:

  • Langchian - 自定义提示词模板 提取结构化的数据
  • 每天掌握一个Linux命令 - hping3
  • Windows 账号管理与安全指南
  • 【深度学习新浪潮】以Dify为例的大模型平台的对比分析
  • Torch Geometric GCN训练心得
  • selenium-自动更新谷歌浏览器驱动
  • 从多巴胺的诱惑到内啡肽的力量 | 个体成长代际教育的成瘾困局与破局之道
  • NLP学习路线图(十九):GloVe
  • 香橙派3B学习笔记5:Linux文件系统分区_A/B系统分区
  • 【C++】23. unordered_map和unordered_set的使用
  • 【深度学习新浪潮】多模态模型如何处理任意分辨率输入?
  • Qt信号与槽机制深度解析
  • 图像任务中的并发处理:线程池、Ray、Celery 和 asyncio 的比较
  • Posix API
  • FPGA仿真中阻塞赋值(=)和非阻塞赋值(<=)区别
  • SystemVerilog—Interface语法(二)
  • 【性能调优系列】深入解析火焰图:从基础阅读到性能优化实战
  • 汽车软件 OTA 升级技术发展现状与趋势
  • uniApp页面交互
  • MySQL DDL操作全解析:从入门到精通,包含索引视图分区表等全操作解析
  • 深圳市政府网站建设公司/外链网址
  • 如何做一个免费的网站/热门搜索
  • 网页微信版文件传输助手/开源seo软件
  • .vip域名做网站/深圳aso优化
  • 网站流量100g/全国疫情最新
  • 其它区便宜营销型网站建设/发布软文的平台有哪些