当前位置: 首页 > 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;
}

http://www.xdnf.cn/news/770977.html

相关文章:

  • 数据治理的演变与AI趋势
  • 零基础开始的网工之路第十七天------计算机网络知识
  • 机器学习——集成学习
  • STM32入门教程——GPIO输入
  • 使用Mathematica观察多形式根的分布随参数的变化
  • mysql数据库实现分库分表,读写分离中间件sharding-sphere
  • 数据库MySQL集群MGR
  • NiceGUI 是一个基于 Python 的现代 Web 应用框架
  • PyTorch——卷积层(3)
  • MapReduce(期末速成版)
  • 检索器组件深入学习与使用技巧 VectorStoreRetriever 检索器
  • android binder(二)应用层编程实例
  • 基于 Android 和 JBox2D 的简单小游戏
  • 【短距离通信】【WiFi】精讲WLAN 驱动结构
  • Android Studio 之基础代码解析
  • wow Warlock shushia [Dreadsteed]
  • 【Java EE初阶 --- 多线程(初阶)】多线程的实现案例
  • 《Effective Python》第六章 推导式和生成器——使用 yield from 组合多个生成器
  • 嵌入式学习笔记 - FreeRTOS关于vApplicationGetIdleTaskMemory
  • AI书签管理工具开发全记录(九):用户端页面集成与展示
  • opencv 可视化函数
  • 苹果电脑深度清理,让老旧Mac重焕新生
  • MySQL 全量 增量备份与恢复
  • 揭秘 NextJS Script 组件
  • HealthBench医疗AI评估基准:技术路径与核心价值深度分析(上)
  • Redis-6.2.9 cluster集群部署和扩容缩容
  • Flask中secret_key设置解析
  • Spring Boot Starter 自动装配原理全解析:从概念到实践
  • 通用优势估计函数(GAE,Generalized Advantage Estimation)详解
  • unity开发棋牌游戏