Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6a053c2

Browse files
committed
Complete Karen and Supermarket problem
1 parent c25311a commit 6a053c2

File tree

4 files changed

+138
-0
lines changed

4 files changed

+138
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ easily understandable algorithms for learning purposes.
9191
- [792D Paths in a Complete Binary Tree](codeforces/paths-in-complete-binary-tree)
9292
- [796D Police Stations](codeforces/police-stations)
9393
- [796E Exam Cheating](codeforces/exam-cheating)
94+
- [815C Karen and Supermarket](codeforces/karen-and-supermarket)
9495
- [818D Multicolored Cars](codeforces/multicolored-cars)
9596
- [819B Mister B and PR Shifts](codeforces/mister-b-and-pr-shifts)
9697
- [819E Mister B and Flight to the Moon](codeforces/mister-b-and-flight-to-the-moon)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CXX := g++
2+
CXXFLAGS := -std=c++14 -Wall -o out
3+
4+
default: out run
5+
6+
out: main.cpp
7+
$(CXX) $(CXXFLAGS) main.cpp
8+
9+
clean:
10+
$(RM) out
11+
12+
run:
13+
./out
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# README
2+
3+
[http://codeforces.com/problemset/problem/815/C](http://codeforces.com/problemset/problem/815/C)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#include <bits/stdc++.h>
2+
3+
using namespace std; // NOLINT
4+
5+
constexpr int MAX_N = 5000;
6+
7+
constexpr int MAX_B = 1000000000;
8+
9+
constexpr int INF = MAX_B + 1;
10+
11+
int n, b;
12+
13+
int64_t C[MAX_N], D[MAX_N], X[MAX_N];
14+
15+
/**
16+
* T[u] = The set of coupons that can be used after using coupon u.
17+
*/
18+
vector<int> T[MAX_N];
19+
20+
/**
21+
* S[u] = The size of the sub-tree rooted at u.
22+
*/
23+
int S[MAX_N];
24+
25+
/**
26+
* F[u][i] = The minimum cost to buy exactly i items from the sub-tree rooted
27+
* at u using coupons.
28+
*/
29+
int64_t F[MAX_N][MAX_N + 1];
30+
31+
/**
32+
* G[u][i] = The minimum cost to buy exactly i items from the sub-tree rooted
33+
* at u WITHOUT using coupons.
34+
*/
35+
int64_t G[MAX_N][MAX_N + 1];
36+
37+
/**
38+
* Calculates F[v][*] and G[v][*] for all v in the sub-tree rooted at u.
39+
*/
40+
void dfs(int u) {
41+
assert(u >= 0 && u < n);
42+
43+
// This is important to enforce coupon dependencies! Especially in line 58
44+
// when i = 0 but we must buy/use coupon u to use coupons further down the
45+
// tree.
46+
F[u][0] = INF;
47+
F[u][1] = C[u] - D[u];
48+
49+
G[u][0] = 0;
50+
G[u][1] = C[u];
51+
52+
S[u] = 1;
53+
54+
for (int v : T[u]) {
55+
dfs(v);
56+
57+
for (int i = S[u]; i >= 0; i--) {
58+
for (int k = S[v]; k >= 0; k--) {
59+
// We can use a coupon if we bought the parent with a coupon. If we
60+
// also buy item u with a coupon then we can also make use of coupons
61+
// with purchases further down the tree. However we do not have to
62+
// use coupons - it may be cheaper to buy an undiscounted item far
63+
// down the tree with a cheap base price than buying all the items
64+
// leading up to it just to get a discount that does not make up for
65+
// the cost of the path.
66+
F[u][i + k] = min(F[u][i + k], F[u][i] + min(F[v][k], G[v][k]));
67+
68+
// If we cannot use a coupon this property holds for all remaining
69+
// items in this sub-tree.
70+
G[u][i + k] = min(G[u][i + k], G[u][i] + G[v][k]);
71+
}
72+
}
73+
74+
S[u] += S[v];
75+
}
76+
}
77+
78+
/**
79+
* Calculates the maximum number of items that Karen can buy.
80+
*/
81+
int items() {
82+
std::fill(&F[0][0], &F[0][0] + sizeof(F)/ sizeof(F[0][0]), INF);
83+
std::fill(&G[0][0], &G[0][0] + sizeof(G)/ sizeof(G[0][0]), INF);
84+
85+
// Calculate F and G.
86+
dfs(0);
87+
88+
// Find most items that can be bought with budget b in O(log N) time.
89+
int s = 0, lo = 0, hi = n;
90+
91+
while (lo <= hi) {
92+
int m = lo + (hi - lo) / 2;
93+
94+
// Slice search window in half.
95+
if (F[0][m] <= b || G[0][m] <= b) {
96+
s = m;
97+
lo = m + 1;
98+
} else {
99+
hi = m - 1;
100+
}
101+
}
102+
103+
return s;
104+
}
105+
106+
int main() {
107+
cin >> n >> b;
108+
109+
assert(n <= MAX_N);
110+
111+
cin >> C[0] >> D[0];
112+
for (int u = 1; u < n; u++) {
113+
cin >> C[u] >> D[u] >> X[u];
114+
X[u]--;
115+
T[X[u]].push_back(u);
116+
}
117+
118+
cout << items() << endl;
119+
120+
return 0;
121+
}

0 commit comments

Comments
 (0)