Submission #1293238

#TimeUsernameProblemLanguageResultExecution timeMemory
1293238jabaKnapsack (NOI18_knapsack)C++20
100 / 100
37 ms2796 KiB
#include <functional> #include <iostream> #include <unordered_map> #include <unordered_set> #include <string> #include <algorithm> #include <map> #include <list> #include <math.h> #include <cstdlib> #include <fstream> #include <queue> #include <set> #include <vector> #include <stack> #include <bitset> #include <random> #include <chrono> #include <cassert> #include <memory> using namespace std; #define long long long #define chmax(c, m) c = max(c, m) #define chmin(c, m) c = min(c, m) long binPow(long a, long p, long M) { if (p < 0) return 0; if (p == 0) return 1; if (p == 1) return a % M; if (p % 2 == 0) { long v = binPow(a, p / 2, M); return 1ll * v * v % M; } else { long v = binPow(a, p / 2, M); return (1ll * v * v % M) * a % M; } } struct DSU { vector<long> par, sz; DSU(int n) : par(n), sz(n, 1) { for (int i = 0; i < n; i++) par[i] = i; } int getPar(int u) { return par[u] == u ? u : par[u] = getPar(par[u]); } void connect(int u, int v) { u = getPar(u); v = getPar(v); if (u == v) return; if (sz[u] < sz[v]) std::swap(u, v); sz[u] += sz[v]; par[v] = u; } bool isConnected(int u, int v) { return getPar(u) == getPar(v); } }; // class DSU long inv(long a, long M) { return (M - a) % M; } long gcd(long a, long b) { while (a != 0 && b != 0) { if (a >= b) a %= b; else b %= a; } return a + b; } long lcm(long a, long b) { return a * b / gcd(a, b); } class LCA { private: int n, l; vector<vector<pair<long, long>>> adj; int timer; vector<int> tin, tout; vector<vector<pair<long, long>>> up; void dfs(int v, int p, long e) { tin[v] = ++timer; up[v][0].first = p; up[v][0].second = e; for (int i = 1; i <= l; ++i) { up[v][i].first = up[up[v][i - 1].first][i - 1].first; up[v][i].second = max(up[up[v][i - 1].first][i - 1].second, up[v][i - 1].second); } for (auto& u : adj[v]) { if (u.first != p) dfs(u.first, v, u.second); } tout[v] = ++timer; } void preprocess(int root) { tin.resize(n); tout.resize(n); timer = 0; l = ceil(log2(n)); up.assign(n, vector<pair<long, long>>(l + 1)); dfs(root, root, 0); } public: bool is_ancestor(int u, int v) { return tin[u] <= tin[v] && tout[u] >= tout[v]; } int lca(int u, int v) { if (is_ancestor(u, v)) return u; if (is_ancestor(v, u)) return v; for (int i = l; i >= 0; --i) { if (!is_ancestor(up[u][i].first, v)) u = up[u][i].first; } return up[u][0].first; } long getMax(long u, long v) { long lc = lca(u, v); long h = l; long ans = 0; for (int i = h; i >= 0; --i) { if (is_ancestor(lc, up[u][i].first)) { ans = max(ans, up[u][i].second); u = up[u][i].first; } } for (int i = h; i >= 0; --i) { if (is_ancestor(lc, up[v][i].first)) { ans = max(ans, up[v][i].second); v = up[v][i].first; } } return ans; } LCA(long N, long root, vector<vector<pair<long, long>>>& g) { n = N; adj = g; preprocess(root); } }; long phi(long n) { long result = n; for (long i = 2; i * i <= n; ++i) if (n % i == 0) { while (n % i == 0) n /= i; result -= result / i; } if (n > 1) result -= result / n; return result; } struct TwoSatSolver { int n_vars; int n_vertices; vector<vector<int>> adj, adj_t; vector<bool> used; vector<int> order, comp; vector<bool> assignment; TwoSatSolver(int _n_vars) : n_vars(_n_vars), n_vertices(2 * n_vars), adj(n_vertices), adj_t(n_vertices), used(n_vertices), order(), comp(n_vertices, -1), assignment(n_vars) { order.reserve(n_vertices); } void dfs1(int v) { used[v] = true; for (int u : adj[v]) { if (!used[u]) dfs1(u); } order.push_back(v); } void dfs2(int v, int cl) { comp[v] = cl; for (int u : adj_t[v]) { if (comp[u] == -1) dfs2(u, cl); } } bool solve_2SAT() { order.clear(); used.assign(n_vertices, false); for (int i = 0; i < n_vertices; ++i) { if (!used[i]) dfs1(i); } comp.assign(n_vertices, -1); for (int i = 0, j = 0; i < n_vertices; ++i) { int v = order[n_vertices - i - 1]; if (comp[v] == -1) dfs2(v, j++); } assignment.assign(n_vars, false); for (int i = 0; i < n_vertices; i += 2) { if (comp[i] == comp[i + 1]) return false; assignment[i / 2] = comp[i] > comp[i + 1]; } return true; } void add_disjunction(int a, bool na, int b, bool nb) { // na and nb signify whether a and b are to be negated a = 2 * a ^ na; b = 2 * b ^ nb; int neg_a = a ^ 1; int neg_b = b ^ 1; adj[neg_a].push_back(b); adj[neg_b].push_back(a); adj_t[b].push_back(neg_a); adj_t[a].push_back(neg_b); } }; class FenwickTree { private: int64_t* B1; int64_t* B2; int size; void AddOnSingleElement(int index, int64_t* B, int64_t valueToAdd) { while (index < size) { B[index] += valueToAdd; index = (index | (index + 1)); } } int64_t MakeQueryOnPrefix(int lastElementIndex, int64_t* B) { int64_t ans = 0; while (lastElementIndex > 0) { ans += B[lastElementIndex]; lastElementIndex &= (lastElementIndex + 1); lastElementIndex -= 1; } return ans; } public: FenwickTree(int numberOfElements) { B1 = new int64_t[numberOfElements + 1]{ 0 }; B2 = new int64_t[numberOfElements + 1]{ 0 }; size = numberOfElements + 1; } ~FenwickTree() { delete B1; delete B2; } int64_t MakeQueryOnPrefix(int lastElementIndex) { return MakeQueryOnPrefix(lastElementIndex, B1) * lastElementIndex - MakeQueryOnPrefix(lastElementIndex, B2); } int64_t MakeQueryOnSegment(int left, int right) { return MakeQueryOnPrefix(right) - MakeQueryOnPrefix(left); } void AddOnSegment(int left, int right, int64_t valueToAdd) { left += 1; AddOnSingleElement(left, B1, valueToAdd); AddOnSingleElement(right + 1, B1, -valueToAdd); AddOnSingleElement(left, B2, valueToAdd * (left - 1)); AddOnSingleElement(right + 1, B2, -valueToAdd * (right)); } }; namespace SegmentTree { /** * Traits for min on segment and set single element queries (by default) */ template<typename T> struct TraitsMinSet { static T neutral() { return std::numeric_limits<T>::max(); } static void update(T& dst, T src) { dst = src; } static void merge(T& dst, const T& lhs, const T& rhs) { dst = std::min(lhs, rhs); } }; /** * List of additional traits, implemented below */ template<typename T> struct TraitsMaxSet; // max on segment, set single element template<typename T> struct TraitsSumSet; // sum on segment, set single element template<typename T> struct TraitsGCDSet; // gcd on segment, set single element template<typename T> struct TraitsMinAdd; // min on segment, add to single element template<typename T> struct TraitsMaxAdd; // max on segment, add to single element template<typename T> struct TraitsSumAdd; // sum on segment, add to single element template<typename T> struct TraitsGCDAdd; // gcd on segment, add to single element /** * SegmentTree class. Effective bottom-to-top implementation */ template<typename ItemType = int64_t, typename ItemTraits = TraitsMinSet<ItemType>> struct SegmentTree { /** * Public data: `n` - number of items in array and `data` - tree's container */ int n; std::vector<ItemType> data; /** * Main methods: resize(nItems), build(array), get(left, right), where 0 <= left <= right < nItems */ void resize(const int n_) { n = n_; int pow = 1; while (pow < n) { pow *= 2; } data.assign(2 * pow, ItemTraits::neutral()); } template<typename T> void build(const std::vector<T>& arr) { resize((int)arr.size()); for (int v = 0; v < n; ++v) { data[v + n] = arr[v]; } for (int v = n - 1; v >= 1; --v) { ItemTraits::merge(data[v], data[2 * v], data[2 * v + 1]); } } ItemType get(int ql, int qr) const { ItemType ret = ItemTraits::neutral(); for (ql += n, qr += n; ql <= qr; ql /= 2, qr /= 2) { if (ql % 2 == 1) { ItemTraits::merge(ret, ret, data[ql++]); } if (qr % 2 == 0) { ItemTraits::merge(ret, ret, data[qr--]); } } return ret; } void update(int pos, ItemType val) { int v = pos + n; ItemTraits::update(data[v], val); for (v /= 2; v > 0; v /= 2) { ItemTraits::merge(data[v], data[2 * v], data[2 * v + 1]); } } }; /** SegmentTree class end */ /** * Traits for max on segment and set single element queries */ template<typename T> struct TraitsMaxSet { static T neutral() { return std::numeric_limits<T>::min(); } static void update(T& dst, T src) { dst = src; } static void merge(T& dst, const T& lhs, const T& rhs) { dst = std::max(lhs, rhs); } }; /** * Traits for sum on segment and set single element queries */ template<typename T> struct TraitsSumSet { static T neutral() { return T(0); } static void update(T& dst, T src) { dst = src; } static void merge(T& dst, const T& lhs, const T& rhs) { dst = lhs + rhs; } }; /** * Traits for min on segment and add to single element queries */ template<typename T> struct TraitsMinAdd { static T neutral() { return std::numeric_limits<T>::max(); } static void update(T& dst, T src) { dst += src; } static void merge(T& dst, const T& lhs, const T& rhs) { dst = std::min(lhs, rhs); } }; /** * Traits for max on segment and add to single element queries */ template<typename T> struct TraitsMaxAdd { static T neutral() { return std::numeric_limits<T>::min(); } static void update(T& dst, T src) { dst += src; } static void merge(T& dst, const T& lhs, const T& rhs) { dst = std::max(lhs, rhs); } }; /** * Traits for sum on segment and add to single element queries */ template<typename T> struct TraitsSumAdd { static T neutral() { return T(0); } static void update(T& dst, T src) { dst += src; } static void merge(T& dst, const T& lhs, const T& rhs) { dst = lhs + rhs; } }; } /** SegmentTree namespace end */ vector<long> prefix_function(string s) { long n = s.size(); vector<long> p(n + 11); p[0] = 0; for (int i = 2; i <= n; i++) { long len = p[i - 1]; while (s[i - 1] != s[len] && len != 0) { len = p[len]; } if (len == 0) { if (s[0] == s[i - 1]) { p[i] = 1; } else p[i] = 0; } else { p[i] = len + 1; } } return p; } long getSum(long nm) { long ans = 0; while (nm > 0) { ans += nm % 10; nm /= 10; } return ans; } long powLong(long nm, long p) { long ans = 1; for (int i = 0; i < p; i++) { ans *= nm; } return ans; } void solve() { long s, n; cin >> s >> n; vector<vector<pair<long, long>>> push(s + 1); for (int i = 1; i <= n; i++) { long v, w, k; cin >> v >> w >> k; push[w].push_back({v, k}); } vector<long> dp(s + 1, -1e18); dp[0] = 0; for (int i = 1; i <= s; i++) { sort(push[i].begin(), push[i].end()); reverse(push[i].begin(), push[i].end()); long remPush = s / i; for (auto& el : push[i]) { long cntPush = min(remPush, el.second); remPush -= cntPush; for (int pushedCnt = 1; pushedCnt <= cntPush; pushedCnt++) { for (int curW = s; curW >= i; curW--) { chmax(dp[curW], dp[curW - i] + el.first); } } } } long ans = 0; for (int i = 0; i <= s; i++) chmax(ans, dp[i]); cout << ans; } int main() { cin.tie(0); cin.sync_with_stdio(false); long t = 1; //cin >> t; for (int t1 = 0; t1 < t; t1++) { solve(); } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...