力扣竞赛模板
作者:互联网
Debug
void _debug(ostream& os) { os << '\n'; }
template<typename T, typename... Args>
void _debug(ostream& os, const T& t, const Args&... args) {
os << t;
if (sizeof...(args)) {
os << ", ";
}
_debug(os, args...);
}
#define debug(args...) cerr << #args << " = ", _debug(cout, ##args)
并查集
class UnionFindSet {
public:
UnionFindSet(int n): components(n), fa(n + 1), sz(n + 1) {
iota(fa.begin(), fa.end(), 0);
fill(sz.begin(), sz.end(), 1);
}
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
bool merge(int x, int y) {
x = find(x), y = find(y);
if (x == y) {
return false;
}
sz[x] += sz[y], fa[y] = x, --components;
return true;
}
bool isConnected(int x, int y) {
return find(x) == find(y);
}
int components;
vector<int> fa, sz;
};
树状数组
一维
单点修改区间查询
class FenwickTree {
public:
FenwickTree(int _n): n(_n), c(_n + 1) {}
FenwickTree(vector<int>& a) {
n = a.size();
c.resize(n + 1);
for (int i = 0; i < n; ++i) {
add(i + 1, a[i]);
}
}
void add(int i, int k) {
while (i <= n) {
c[i] += k;
i += lowbit(i);
}
}
long long sum(int i) {
long long res = 0;
while (i > 0) {
res += c[i];
i -= lowbit(i);
}
return res;
}
long long sum(int l, int r) {
return sum(r) - sum(l - 1);
}
int lowbit(int x) {
return x & -x;
}
int n;
vector<long long> c;
};
区间修改区间查询
class FenwickTree {
public:
FenwickTree(int _n): n(_n), a(_n + 1), b(_n + 1) {}
FenwickTree(vector<int>& c) {
n = c.size();
a.resize(n + 1);
b.resize(n + 1);
for (int i = 1; i <= n; ++i) {
int d = (i == 1 ? c[i - 1] : c[i - 1] - c[i - 2]);
add(a, i, d);
add(b, i, (i - 1) * d);
}
}
void add(int l, int r, int k) {
add(a, l, k);
add(b, l, k * (l - 1));
add(a, r + 1, -k);
add(b, r + 1, -k * r);
}
void add(vector<long long>& a, int i, int k) {
while (i <= n) {
a[i] += k;
i += lowbit(i);
}
}
long long sum(int l, int r) {
long long x = (l - 1) * sum(a, l - 1) - sum(b, l - 1);
long long y = r * sum(a, r) - sum(b, r);
return y - x;
}
long long sum(vector<long long>& a, int i) {
long long res = 0;
while (i > 0) {
res += a[i];
i -= lowbit(i);
}
return res;
}
int lowbit(int x) {
return x & -x;
}
int n;
vector<long long> a, b;
};
二维
class FenwickTree {
public:
FenwickTree(int n, int m) : n(n), m(m) {
t1 = t2 = t3 = t4 = vector<vector<long long>>(n + 1, vector<long long>(m + 1));
}
FenwickTree(vector<vector<int>>& a) {
n = a.size(), m = a[0].size();
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
add(i, j, a[i - 1][j - 1]);
}
}
}
void add(int x, int y, int k) {
for (int i = x; i <= n; i += lowbit(i)) {
for (int j = y; j <= m; j += lowbit(j)) {
t1[i][j] += k;
t2[i][j] += k * x;
t3[i][j] += k * y;
t4[i][j] += k * x * y;
}
}
}
void add(int x1, int y1, int x2, int y2, int k) {
add(x1, y1, k);
add(x1, y2 + 1, -k);
add(x2 + 1, y1, -k);
add(x2 + 1, y2 + 1, k);
}
long long sum(int x, int y) {
long long res = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
for (int j = y; j > 0; j -= lowbit(j)) {
res += (x + 1) * (y + 1) * t1[i][j] - (y + 1) * t2[i][j] - (x + 1) * t3[i][j] + t4[i][j];
}
}
return res;
}
long long sum(int x1, int y1, int x2, int y2) {
return sum(x2, y2) - sum(x2, y1 - 1) - sum(x1 - 1, y2) + sum(x1 - 1, y1 - 1);
}
int lowbit(int x) {
return x & -x;
}
int n, m;
vector<vector<long long>> t1, t2, t3, t4;
};
最短路
typedef pair<long long, int> P;
const static long long LINF = (1LL << 60);
vector<long long> dijkstra(vector<vector<pair<int, int>>>& e, int s) {
vector<long long> d((int)e.size(), LINF);
priority_queue<P, vector<P>, greater<>> q;
d[s] = 0LL, q.emplace(0LL, s);
while (!q.empty()) {
auto [du, u] = q.top();
q.pop();
if (du != d[u]) {
continue;
}
for (auto& [v, w] : e[u]) {
if (d[u] + w < d[v]) {
d[v] = d[u] + w;
q.emplace(d[v], v);
}
}
}
return d;
}
字符串哈希
const static ULL P = 13331;
typedef unsigned long long ULL;
vector<ULL> h(n + 1), rh(n + 1), p(n + 1);
p[0] = 1;
for (int i = 1; i <= n; ++i) {
h[i] = h[i - 1] * P + s[i - 1];
rh[i] = rh[i - 1] * P + s[n - i];
p[i] = p[i - 1] * P;
}
ULL get(int l, int r, vector<ULL>& hash) {
return hash[r] - hash[l - 1] * p[r - l + 1];
}
bool isPalindrome(int l, int r, vector<ULL>& hash, vector<ULL> rhash) {
return get(l, r, h) == get(n - r + 1, n - l + 1, rh);
}
平衡树
$.order_of_key(k) -> 查找k在集合的排名(从0开始)
$.find_by_order(k) -> 查找集合中第k大(从0开始)
$.lower_bound(k)
$.upper_bound(k)
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
template<class T> using
ordered_set =
tree<T, null_type, less<T>, rb_tree_tag,
tree_order_statistics_node_update>;
template<class T> using
ordered_multiset =
tree<T, null_type, less_equal<T>, rb_tree_tag,
tree_order_statistics_node_update>;
template<class T, class U> using
ordered_map =
tree<T, U, less<T>, rb_tree_tag,
tree_order_statistics_node_update>;
template<class T, class U> using
ordered_multimap =
tree<T, U, less_equal<T>, rb_tree_tag,
tree_order_statistics_node_update>;
01背包(完全背包将V枚举反过来)
最大价值
int bag01(vector<pair<int, int>>& items, int V) {
vector<int> dp(V + 1);
for (auto& [v, w]: items) {
for (int j = V; j >= v; --j) {
dp[j] = max(dp[j], dp[j - v] + w);
}
}
return dp[V];
}
最大价值方案数
int bag01(vector<pair<int, int>>& items, int V) {
vector<int> dp(V + 1), cnt(V + 1, 1);
for (auto& [v, w]: items) {
for (int j = V; j >= v; --j) {
if (dp[j] < dp[j - v] + w) {
cnt[j] = cnt[j - v];
} else if (dp[j] == dp[j - v] + w) {
cnt[j] = (cnt[j] + cnt[j - v]) % P;
}
dp[j] = max(dp[j], dp[j - v] + w);
}
}
return cnt[V];
}
最大价值并打印字典序最小方案
vector<int> bag01(vector<pair<int, int>>& items, int V) {
int N = items.size();
vector<vector<int>> dp(N + 1, vector<int>(V + 1));
for (int i = N; i >= 1; --i) {
auto& [v, w] = items[i - 1];
for (int j = 0; j <= V; ++j) {
dp[i][j] = dp[i + 1][j];
if (j >= v) {
dp[i][j] = max(dp[i][j], dp[i + 1][j - v] + w);
}
}
}
vector<int> ans;
for (int i = 1, j = V; i <= N; ++i) {
auto& [v, w] = items[i - 1];
if (j >= v && dp[i][j] == dp[i + 1][j - v] + w) {
ans.push_back(i);
j -= v;
}
}
return ans;
}
装满时最大\(/\)最小价值
const static int inf = (-1 << 30);
const static int INF = (1 << 30);
int bag01(vector<pair<int, int>>& items, int V) {
vector<int> dp(V + 1, INF);
// vector<int> dp(V + 1, inf);
dp[0] = 0;
for (auto& [v, w]: items) {
for (int j = V; j >= v; --j) {
dp[j] = max(dp[j], dp[j - v] + w);
// dp[j] = min(dp[j], dp[j - v] + w);
}
}
return (dp[V] != INF ? dp[V] : -1);
}
背包装满时方案数
int bag01(vector<int>& items, int V) {
vector<int> dp(V + 1);
dp[0] = 1;
for (int& v: items) {
for (int j = V; j >= v; --j) {
dp[j] = (dp[j] + dp[j - v]) % MOD;
}
}
return dp[V];
}
装满时且最大\(/\)最小价值时方案数
const static int inf = (-1 << 30);
const static int INF = (1 << 30);
int bag01(vector<pair<int, int>>& items, int V) {
vector<int> dp(V + 1, inf), cnt(V + 1);
// vector<int> dp(V + 1, INF), cnt(V + 1);
dp[0] = 0, cnt[0] = 1;
for (auto& [v, w]: items) {
for (int j = V; j >= v; --j) {
if (dp[j] > dp[j - v] + w) {
cnt[j] = cnt[j - v];
} else if (dp[j] == dp[j - v] + w) {
cnt[j] = (cnt[j] + cnt[j - v]) % MOD;
}
dp[j] = max(dp[j], dp[j - v] + w);
// if (dp[j] < dp[j - v] + w) {
// cnt[j] = cnt[j - v];
// } else if (dp[j] == dp[j - v] + w) {
// cnt[j] = (cnt[j] + cnt[j - v]) % MOD;
// }
// dp[j] = min(dp[j], dp[j - v] + w);
}
}
return cnt[V];
}
分组背包
int bagGroup(vector<vector<pair<int, int>>>& items, int V) {
vector<int> dp(V + 1);
for (auto& item : items) {
for (int j = V; j >= 0; --j) {
for (auto& [v, w] : item) {
if (j >= v) {
dp[j] = max(dp[j], dp[j - v] + w);
}
}
}
}
return dp[V];
}
标签:cnt,竞赛,return,int,items,力扣,vector,模板,dp 来源: https://www.cnblogs.com/stler098/p/16100853.html