├── Atcoder ├── Atcoder-DP-Intervals.cpp ├── Atcoder002-AGC-D.cpp ├── Atcoder027-AGC-C.cpp ├── Atcoder034-AGC-B.cpp ├── Atcoder079-ARC-B.cpp ├── Atcoder145-ABC-F.py ├── Atcoder150-ABC-E.java ├── Atcoder158-ABC-D.cpp ├── Atcoder158-ABC-E.cpp └── Atcoder158-ABC-F.cpp ├── CSAcademy └── temp.txt ├── CodeChef └── CODECHEF-BJUDGE.cpp ├── CodeForces ├── CF101149-gym-M.cpp ├── CF101498-GYM-L.cpp ├── CF101864-GYM-K.cpp ├── CF1045-D1-C.cpp ├── CF1110-D12-F.cpp ├── CF149-D2-E.cpp ├── CF178-D2-F3.cpp ├── CF297-D1-C.cpp ├── CF331-D12-C3.cpp ├── CF38-D12-G.cpp ├── CF455-D1-E.cpp ├── CF526-D12-F.cpp ├── CF547-D1-E.cpp ├── CF551-D2-E.cpp ├── CF555-D1-E.cpp ├── CF68-D12-D.cpp ├── CF704-D1-B.cpp ├── CF713-D1-B.cpp ├── CF722-D2-E.cpp ├── CF802-D12-K.cpp ├── CF835-D2-E.cpp ├── CF872-D2-D.cpp ├── CF896-D1-E.cpp ├── CF897-D2-D.cpp ├── CF909-D2-F.cpp ├── CF914-D12-E.cpp ├── CF916-D2-D.cpp ├── CF916-D2-E.cpp ├── CF932-D2-F.cpp ├── CF936-D1-C.cpp ├── CF939-D2-F.cpp └── CF997-D1-E.cpp ├── Evaluator ├── o57_apr18_palmcake.cpp ├── o57_apr18_unfollow.cpp ├── o57_apr19_cp.cpp ├── o57_apr26_orepi.cpp ├── o58_apr22_prettycut.cpp ├── o58_apr23_hiking.cpp ├── o58_apr25_convexways.cpp ├── o58_apr25_islands_TLE.cpp ├── o58_apr25_light.cpp ├── o58_apr27_landwall.cpp ├── o58_apr30_citrus.cpp ├── o59_may05_boxes.cpp ├── o59_may05_pointsonstrip.cpp ├── o59_may09_trio.cpp ├── o59_may10_improvement.cpp ├── o60_may10_parade.cpp ├── o61_mar_c1_cycletax.cpp ├── o61_mar_c1_pyramid.cpp ├── o61_mar_c1_salary.cpp ├── o61_mar_c1_traffic.cpp ├── o61_may02_bread.cpp ├── o61_may10_plague.cpp ├── o61_may10_trail.cpp ├── o61_oct_c1_charprint.cpp ├── o61_oct_c1_knives.cpp ├── o61_oct_c2_longpipe.cpp ├── o62_mar_c1_dontfight.cpp ├── o62_mar_c1_edgecolor.cpp ├── o62_mar_c1_flat2.cpp ├── o62_mar_c1_socks.cpp ├── o62_mar_c2_blind.cpp ├── o62_mar_c2_outoforder.cpp ├── o62_mar_c2_treesim.cpp ├── o62_may07_bts.cpp ├── o62_may07_camp.cpp ├── o62_may07_marathon.cpp ├── o62_may09_parent.cpp ├── o62_may11_insert.cpp ├── o62_may11_twomachinejobs.cpp ├── o62_may15_candyreserve.cpp ├── o62_may15_repeats.cpp ├── o62_may15_triquery.cpp ├── o62_may16_fanclub.cpp ├── o62_may16_gg.cpp └── o62_may16_polesropes.cpp ├── GoogleCodeJam ├── CODEJAM08-R1A-A.rs ├── CODEJAM08-R1A-B.rs ├── CODEJAM09-R1A-C.cpp └── CODEJAM19-QR-C.py ├── Hackerearth └── temp.txt ├── Hackerrank ├── HACKR house-location.cpp ├── HACKR neighborhood-queries.cpp └── IOIPractice14-bouncebouncebounce.cpp ├── LiveArchive └── 7577.cpp ├── Olympiad ├── APIO │ ├── APIO08-roads.cpp │ ├── APIO10-patrol.cpp │ ├── APIO11-color.cpp │ ├── APIO16-boat.cpp │ ├── APIO16-fireworks.cpp │ ├── APIO17-merchant.cpp │ └── APIO18-duathlon.cpp ├── Balkan │ ├── Balkan11-timeismoney.cpp │ ├── Balkan17-Cats.cpp │ ├── Balkan17-monsters.cpp │ └── Balkan18-election.cpp ├── Baltic │ ├── Baltic09-candy.cpp │ ├── Baltic17-PoliticalDevelopment.cpp │ ├── Baltic17-Railway.cpp │ ├── Baltic17-toll.cpp │ └── BalticWarmup17-toast.cpp ├── CCO │ └── CCO18-GradientDescent.cpp ├── CEOI │ ├── CEOI13-treasure.cpp │ ├── CEOI15-indcyc.cpp │ └── CEOI15-teams.cpp ├── COCI │ ├── COCI16-zoltan.cpp │ ├── COCI18-strah.cpp │ ├── COCI18-suncanje.cpp │ ├── COCI19-parametriziran.cpp │ ├── COCI19-simfonija.cpp │ ├── COCI19-slicice.cpp │ └── COCI19-transport.cpp ├── COI │ └── COI06-patrik.cpp ├── IOI │ ├── IOI05-birthday.cpp │ ├── IOI05-mountains.cpp │ └── IOI18-doll.cpp ├── IZhO │ └── IZhO18-segments.cpp ├── JOI │ ├── JOIHO13-bubblesort.cpp │ ├── JOIOC17-amusementPark-Ioi.cpp │ ├── JOIOC17-amusementPark-Joi.cpp │ ├── JOISC17-portfacility.cpp │ ├── JOISC18-airline-Alice.cpp │ ├── JOISC18-airline-Bob.cpp │ ├── JOISC18-bitaro.cpp │ ├── JOISC18-construction.cpp │ └── JOISC19-examination.cpp ├── NOI │ └── NOI19-feast.cpp ├── POI │ ├── POI11-Rotation.cpp │ ├── POI11-Rotation2.cpp │ ├── POI13-price.cpp │ └── POI14-panels.cpp ├── TOKI │ └── TOKIOpen18-CellsTour.cpp ├── USACO │ ├── USACO16mar-262144-plat.cpp │ ├── USACO17dec-standingout-plat.cpp │ ├── USACO17feb-friendcross-plat.cpp │ ├── USACO18dec-gathering-plat.cpp │ ├── USACO18dec-itout-plat.cpp │ ├── USACO18mar-disrupt-plat.cpp │ ├── USACO18mar-sort-gold.cpp │ ├── USACO18mar-sort-plat.cpp │ ├── USACO19jan-redistricting-plat.cpp │ └── USACO19mar-valleys-plat.cpp └── infoarena │ ├── puncte.cpp │ └── tricolor.cpp ├── PKU └── temp.txt ├── README.md ├── SPOJ ├── GOT.cpp ├── GSS2.cpp ├── GSS6.cpp ├── INCDSEQ.cpp ├── MCAMP.cpp ├── SUBLEX.cpp └── XXXXXXXX.cpp ├── TJU └── temp.txt ├── Techjam ├── A.cpp ├── C.cpp └── D.cpp ├── Timus └── temp.txt ├── TopCoder ├── SRM465-D1-600.cpp └── temp.txt └── UVA └── UVA1194.cpp /Atcoder/Atcoder-DP-Intervals.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define long long long 3 | using namespace std; 4 | const int N = 1 << 18; 5 | const long LINF = 1e16; 6 | 7 | int n, m; 8 | long ans; 9 | vector > lsl[N], lsr[N]; 10 | long t[2*N], lz[2*N], dp[N], isect[N]; 11 | 12 | long f[N]; 13 | void update_fen(int i, long v) { 14 | while(i < N) f[i] += v, i += i & -i; 15 | } 16 | 17 | long query_fen(int i) { 18 | long ret = 0; 19 | while(i > 0) ret += f[i], i -= i & -i; 20 | return ret; 21 | } 22 | 23 | void apply(int i) { 24 | if(!lz[i]) return; 25 | t[i] += lz[i]; 26 | if(i < N) { 27 | lz[i << 1] += lz[i]; 28 | lz[i << 1 | 1] += lz[i]; 29 | } 30 | lz[i] = 0; 31 | } 32 | 33 | void update(int tl, int tr, long v, int i = 1, int l = 0, int r = N-1) { 34 | apply(i); 35 | if(r < tl || l > tr) return; 36 | if(tl <= l && r <= tr) { 37 | lz[i] += v; 38 | apply(i); 39 | return; 40 | } 41 | int mid = l+r >> 1; 42 | update(tl, tr, v, i << 1, l, mid); 43 | update(tl, tr, v, i << 1 | 1, mid+1, r); 44 | t[i] = max(t[i << 1], t[i << 1 | 1]); 45 | } 46 | 47 | long query(int tl, int tr, int i = 1, int l = 0, int r = N-1) { 48 | apply(i); 49 | if(r < tl || l > tr) return -LINF; 50 | if(tl <= l && r <= tr) { 51 | return t[i]; 52 | } 53 | int mid = l+r >> 1; 54 | return max(query(tl, tr, i << 1, l, mid), query(tl, tr, i << 1 | 1, mid+1, r)); 55 | } 56 | 57 | int main() { 58 | ios::sync_with_stdio(false); 59 | cin.tie(0); 60 | cin >> n >> m; 61 | for(int i = 0, l, r, a; i < m; i++) { 62 | cin >> l >> r >> a; 63 | lsr[r].emplace_back(l, a); 64 | lsl[l].emplace_back(r, a); 65 | update_fen(l, a); 66 | update_fen(r+1, -a); 67 | } 68 | for(int i = 1; i <= n; i++) { 69 | isect[i] = query_fen(i); 70 | dp[i] = query(0, i-1) + isect[i]; 71 | ans = max(dp[i], ans); 72 | update(i, i, dp[i]); 73 | for(auto p: lsl[i]) { 74 | int r, a; 75 | tie(r, a) = p; 76 | update(i, r, -a); 77 | } 78 | for(auto p: lsr[i]) { 79 | int l, a; 80 | tie(l, a) = p; 81 | update(l, i, a); 82 | } 83 | } 84 | cout << ans; 85 | } 86 | -------------------------------------------------------------------------------- /Atcoder/Atcoder002-AGC-D.cpp: -------------------------------------------------------------------------------- 1 | // parallel binary search with DSU 2 | #include 3 | using namespace std; 4 | #define long long long 5 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 6 | const int INF = 1e9+1; 7 | const double EPS = 1e-10; 8 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 9 | const int N = 1e5+1; 10 | 11 | class TaskD { 12 | int n, m, q, x[N], y[N], z[N], l[N], r[N], dsu[N]; 13 | vector > edges; 14 | vector qq[N]; 15 | 16 | int root(int v) { return (dsu[v] < 0 ? v : dsu[v] = root(dsu[v])); } 17 | 18 | void merge(int u, int v) { 19 | if((u = root(u)) == (v = root(v))) return; 20 | dsu[u] += dsu[v]; 21 | dsu[v] = u; 22 | } 23 | 24 | public: 25 | void run(istream &cin, ostream &cout) { 26 | fill_n(dsu+1, n, -1); 27 | cin >> n >> m; 28 | for(int i = 0, u, v; i < m; i++) { 29 | cin >> u >> v; 30 | edges.emplace_back(u, v); 31 | } 32 | cin >> q; 33 | for(int i = 0; i < q; i++) { 34 | cin >> x[i] >> y[i] >> z[i]; 35 | l[i] = 0, r[i] = m-1; 36 | } 37 | for(int t = 0; t < 20; t++) { 38 | fill_n(dsu+1, n, -1); 39 | for(int i = 0; i < m; i++) qq[i].clear(); 40 | for(int i = 0; i < q; i++) if(l[i] != r[i]) { 41 | qq[l[i] + r[i] >> 1].push_back(i); 42 | } 43 | for(int i = 0; i < m; i++) { 44 | merge(edges[i].first, edges[i].second); 45 | for(int qi: qq[i]) { 46 | int rtx = root(x[qi]), rty = root(y[qi]); 47 | int cnt = (rtx == rty ? -dsu[rtx] : -dsu[rtx] -dsu[rty]); 48 | if(cnt >= z[qi]) r[qi] = i; 49 | else l[qi] = i+1; 50 | } 51 | } 52 | } 53 | for(int i = 0; i < q; i++) cout << l[i]+1 << '\n'; 54 | } 55 | }; 56 | 57 | class Solver { 58 | public: 59 | void solve(std::istream& in, std::ostream& out) { 60 | TaskD *obj = new TaskD(); 61 | obj->run(in, out); 62 | } 63 | }; 64 | 65 | int main() { 66 | ios::sync_with_stdio(false); 67 | cin.tie(0); 68 | Solver solver; 69 | std::istream& in(std::cin); 70 | std::ostream& out(std::cout); 71 | solver.solve(in, out); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /Atcoder/Atcoder027-AGC-C.cpp: -------------------------------------------------------------------------------- 1 | // Repeatedly invalidate vertices (ones that don't have both options for A and B adjacent to it). 2 | // Magnificently, we can do this with a queue, which resembles BFS 3 | // We simply have to check if there is still a valid connected component. We don't even need DSU for this. 4 | #include 5 | using namespace std; 6 | #define long long long 7 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 8 | const int INF = 1e9+1; 9 | const double EPS = 1e-10; 10 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 11 | const int N = 2e5+1; 12 | 13 | class TaskC { 14 | int n, m, cnt[N][2]; 15 | bool removed[N]; 16 | string s; 17 | vector g[N]; 18 | 19 | public: 20 | TaskC() { 21 | memset(cnt, 0, sizeof(cnt)); 22 | memset(removed, 0, sizeof(removed)); 23 | } 24 | void solve(istream& cin, ostream& cout) { 25 | cin >> n >> m >> s; 26 | for(int i = 0, u, v; i < m; i++) { 27 | cin >> u >> v; 28 | --u, --v; 29 | g[u].push_back(v); 30 | g[v].push_back(u); 31 | ++cnt[u][s[v] == 'B']; 32 | ++cnt[v][s[u] == 'B']; 33 | } 34 | queue q; 35 | for(int i = 0; i < n; i++) if(!cnt[i][0] || !cnt[i][1]) q.push(i), removed[i] = true; 36 | while(!q.empty()) { 37 | int u = q.front(); 38 | q.pop(); 39 | for(int v: g[u]) { 40 | --cnt[v][s[u] == 'B']; 41 | if(!removed[v] && (!cnt[v][0] || !cnt[v][1])) { 42 | q.push(v); 43 | removed[v] = true; 44 | } 45 | } 46 | } 47 | int ans = 0; 48 | for(int i = 0; i < n; i++) ans += !removed[i]; 49 | assert(ans || ans != 1); 50 | cout << (ans ? "Yes" : "No") << endl; 51 | } 52 | }; 53 | 54 | int main() { 55 | ios::sync_with_stdio(false); 56 | cin.tie(0); 57 | TaskC solver; 58 | std::istream& in(std::cin); 59 | std::ostream& out(std::cout); 60 | solver.solve(in, out); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /Atcoder/Atcoder034-AGC-B.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * code generated by JHelper 3 | * More info: https://github.com/AlexeyDmitriev/JHelper 4 | * @author 5 | */ 6 | 7 | /* INCLUDES */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | using namespace std; 33 | 34 | /* TYPES */ 35 | #define long int64_t 36 | #define all(v) v.begin(), v.end() 37 | typedef pair pii; 38 | typedef pair pli; 39 | typedef pair pll; 40 | typedef vector vi; 41 | typedef vector > vpi; 42 | typedef vector vs; 43 | typedef vector > vvi; 44 | typedef vector > vvl; 45 | 46 | /* CONSTANTS */ 47 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 48 | const int INF = 1e9+1; 49 | const double EPS = 1e-10; 50 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 51 | 52 | /* FUNCTIONS */ 53 | template inline void setMin(T &x, U y) { if(y < x) x = y; } 54 | template inline void setMax(T &x, U y) { if(x < y) x = y; } 55 | template 56 | inline T gcd(T a, T b) { 57 | T c; 58 | while(b) c = b, b = a % b, a = c; 59 | return a; 60 | } 61 | template 62 | inline T square(T a, T b) { return a*b; } 63 | 64 | class TaskB { 65 | 66 | string s; 67 | vpi segs; 68 | long ans; 69 | 70 | public: 71 | void solve(istream &cin, ostream &cout) { 72 | cin >> s; 73 | for(int i = 0, last = 0; i < s.length() - 1; i++) { 74 | if(s[i] == 'B' && s[i+1] == 'C') { 75 | segs.emplace_back(last, i - 1); 76 | last = i + 2; 77 | } 78 | } 79 | auto getAs = [&] (int l, int r) -> int { 80 | int ret = 0; 81 | for(int i = r; i >= l && s[i] == 'A'; i--) { 82 | ++ret; 83 | } 84 | return ret; 85 | }; 86 | reverse(all(segs)); 87 | long furthest = 1; 88 | for(pii seg: segs) { 89 | long As = getAs(seg.first, seg.second); 90 | // cerr << seg.first << ' ' << seg.second << ' ' << As << ' ' << furthest << endl; 91 | ans += As * furthest; 92 | if(As != seg.second - seg.first + 1) furthest = 1; 93 | else ++furthest; 94 | } 95 | cout << ans << endl; 96 | } 97 | }; 98 | 99 | class Solver { 100 | public: 101 | void solve(std::istream& in, std::ostream& out) { 102 | TaskB *obj = new TaskB(); 103 | obj->solve(in, out); 104 | delete obj; 105 | } 106 | }; 107 | 108 | int main() { 109 | ios::sync_with_stdio(false); 110 | cin.tie(0); 111 | Solver solver; 112 | std::istream& in(std::cin); 113 | std::ostream& out(std::cout); 114 | solver.solve(in, out); 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /Atcoder/Atcoder079-ARC-B.cpp: -------------------------------------------------------------------------------- 1 | // https://img.atcoder.jp/arc079/editorial.pdf 2 | #include 3 | using namespace std; 4 | #define long long long 5 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 6 | const int INF = 1e9+1; 7 | const double EPS = 1e-10; 8 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 9 | 10 | class TaskD { 11 | 12 | long k, n, a[51]; 13 | 14 | public: 15 | void solve(istream &cin, ostream &cout) { 16 | cin >> k; 17 | n = 50; 18 | long f = k / n; 19 | for(int i = 0; i < n; i++) a[i] = n-1 + f; 20 | for(int i = 0; i < k % n; i++) { 21 | a[i] += n; 22 | for(int j = 0; j < n; j++) if(j != i) --a[j]; 23 | } 24 | cout << n << endl; 25 | for(int i = 0; i < n; i++) cout << a[i] << ' '; 26 | } 27 | }; 28 | 29 | class Solver { 30 | public: 31 | void solve(std::istream& in, std::ostream& out) { 32 | TaskD *obj = new TaskD(); 33 | obj->solve(in, out); 34 | delete obj; 35 | } 36 | }; 37 | 38 | int main() { 39 | ios::sync_with_stdio(false); 40 | cin.tie(0); 41 | Solver solver; 42 | std::istream& in(std::cin); 43 | std::ostream& out(std::cout); 44 | solver.solve(in, out); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /Atcoder/Atcoder145-ABC-F.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=invalid-name 2 | # pylint: disable=missing-docstring 3 | 4 | # RUN ON PYPY3 5 | 6 | 7 | def main(): 8 | N, K = map(int, input().split()) 9 | H = [0] + [int(x) for x in input().split()] 10 | DP = [[-1 for _ in range(K + 1)] for _ in range(N + 1)] 11 | DP[0] = [0 for _ in range(K + 1)] 12 | for i in range(1, N + 1): 13 | for j in range(K + 1): 14 | for k in range(max(i - j - 1, 0), i): 15 | previous = DP[k][j - (i - k - 1)] 16 | if previous == -1: 17 | continue 18 | 19 | if DP[i][j] == -1 or previous + max(H[i] - H[k], 0) < DP[i][j]: 20 | DP[i][j] = previous + max(H[i] - H[k], 0) 21 | 22 | if j > 0 and DP[i][j - 1] != -1 and DP[i][j - 1] < DP[i][j]: 23 | DP[i][j] = DP[i][j - 1] 24 | ans = -1 25 | for i in range(N + 1): 26 | if K < (N - i): 27 | continue 28 | if ans == -1 or DP[i][min(K - (N - i), K)] < ans: 29 | ans = DP[i][min(K - (N - i), K)] 30 | print(ans) 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /Atcoder/Atcoder150-ABC-E.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Scanner; 3 | 4 | public class Main { 5 | 6 | static final long MOD = (long) (1e9 + 7); 7 | static int n; 8 | static long[] a; 9 | static long[] f; 10 | static long[] inv; 11 | static long[] C; 12 | static long[] P; 13 | static long[] F; 14 | 15 | private static long modPow(long b, long e) { 16 | if(e == 0) return 1; 17 | if(e == 1) return b; 18 | return modPow(b*b % MOD, e >> 1) * modPow(b, e & 1) % MOD; 19 | } 20 | 21 | public static void main(String[] args) { 22 | Scanner sc = new Scanner(System.in); 23 | n = sc.nextInt(); 24 | // Setup 25 | f = new long[n + 1]; 26 | f[0] = 1; 27 | for(int i = 1; i <= n; i++) f[i] = f[i-1] * i % MOD; 28 | inv = new long[n + 1]; 29 | inv[0] = 1; 30 | for(int i = 1; i <= n; i++) inv[i] = modPow(f[i], MOD - 2); 31 | C = new long[n + 1]; 32 | for(int i = 1; i <= n; i++) C[i] = f[n] * inv[n - i] % MOD * inv[i] % MOD; 33 | P = new long[2 * n + 10]; 34 | P[0] = 1; 35 | for(int i = 1; i < P.length; i++) { 36 | P[i] = P[i-1] * 2 % MOD; 37 | } 38 | // F denotes the sum of kC(n, k) from 0 to n (used to calculate final answer) 39 | // F was found through observation (trial/error) that 40 | // F[i]/F[i-1] = (F[i-1] - F[i-2])/(F[i-2] - F[i-3]) 41 | F = new long[Integer.max(n + 1, 3)]; 42 | F[0] = 0; 43 | F[1] = 1; 44 | F[2] = 4; 45 | for(int i = 3; i <= n; i++) { 46 | F[i] = F[i-1] * (F[i-1] - F[i-2]) % MOD * modPow(F[i-2] - F[i-3], MOD - 2) % MOD; 47 | } 48 | a = new long[n + 1]; 49 | for(int i = 1; i <= n; i++) a[i] = sc.nextInt(); 50 | Arrays.sort(a); 51 | for(int i = 1; i <= n / 2; i++) { 52 | long tmp = a[i]; 53 | a[i] = a[n - i + 1]; 54 | a[n - i + 1] = tmp; 55 | } 56 | 57 | 58 | // Compute final answer 59 | long ans = 0; 60 | for(int i = 1; i <= n; i++) { 61 | // F[i-1] + P[i-1] because we had (k+1)C(n, k) from the form above 62 | // so we can just factor a sum of C(n, k) out to get 2^n 63 | ans += (F[i-1] + P[i-1]) * a[i] % MOD * P[n - i] % MOD; 64 | ans %= MOD; 65 | } 66 | 67 | ans *= P[n]; 68 | ans %= MOD; 69 | if(ans < 0) ans += MOD; 70 | System.out.println(ans); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Atcoder/Atcoder158-ABC-D.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * code generated by JHelper 3 | * More info: https://github.com/AlexeyDmitriev/JHelper 4 | * @author 5 | */ 6 | 7 | #include 8 | using namespace std; 9 | 10 | /* TYPES */ 11 | #define long int64_t 12 | #define all(v) v.begin(), v.end() 13 | #define fs first 14 | #define sc second 15 | typedef pair pii; 16 | typedef pair pli; 17 | typedef pair pll; 18 | typedef vector vi; 19 | typedef vector > vpi; 20 | typedef vector vs; 21 | typedef vector > vvi; 22 | typedef vector > vvl; 23 | 24 | /* CONSTANTS */ 25 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 26 | const int INF = 1e9+1; 27 | const double EPS = 1e-10; 28 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 29 | 30 | /* FUNCTIONS */ 31 | template inline void setMin(T &x, U y) { if(y < x) x = y; } 32 | template inline void setMax(T &x, U y) { if(x < y) x = y; } 33 | template 34 | inline T gcd(T a, T b) { 35 | T c; 36 | while(b) c = b, b = a % b, a = c; 37 | return a; 38 | } 39 | template 40 | inline T square(T a) { return a*a; } 41 | 42 | class TaskD { 43 | 44 | deque receive_string_and_convert(istream &cin, ostream &cout) { 45 | string S; 46 | cin >> S; 47 | deque dq; 48 | dq.insert(dq.end(), S.begin(), S.end()); 49 | return dq; 50 | } 51 | 52 | public: 53 | void solve(istream &cin, ostream &cout) { 54 | deque dq = receive_string_and_convert(cin, cout); 55 | bool state = 0; 56 | 57 | int Q; 58 | cin >> Q; 59 | for (int _i = 0; _i < Q; _i++) { 60 | int T; 61 | cin >> T; 62 | if (T == 1) { 63 | state ^= 1; 64 | } else { 65 | int F; 66 | char C; 67 | cin >> F >> C; 68 | --F; 69 | if (F ^ state) { 70 | dq.push_back(C); 71 | } else { 72 | dq.push_front(C); 73 | } 74 | } 75 | } 76 | 77 | string result = ""; 78 | while (!dq.empty()) { 79 | result += dq.front(); 80 | dq.pop_front(); 81 | } 82 | if (state) { 83 | reverse(result.begin(), result.end()); 84 | } 85 | cout << result << endl; 86 | } 87 | }; 88 | 89 | 90 | class Solver { 91 | public: 92 | void solve(std::istream& in, std::ostream& out) { 93 | TaskD *obj = new TaskD(); 94 | obj->solve(in, out); 95 | delete obj; 96 | } 97 | }; 98 | 99 | int main() { 100 | ios::sync_with_stdio(false); 101 | cin.tie(0); 102 | Solver solver; 103 | std::istream& in(std::cin); 104 | std::ostream& out(std::cout); 105 | solver.solve(in, out); 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /CSAcademy/temp.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galletas1712/CompetitiveProgramming/48f546f83bcab17211e9cea5a35edc1968344290/CSAcademy/temp.txt -------------------------------------------------------------------------------- /CodeChef/CODECHEF-BJUDGE.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define all(a) begin(a), end(a) 4 | #define csz(a) (int) a.size() 5 | #define pb push_back 6 | #define epb emplace_back 7 | #define load(a, v) fill(begin(a), end(a), v) 8 | #define load_mem(a, v) memset(a, v, sizeof(a)); 9 | #define iostream_optimize() ios::sync_with_stdio(false); cin.tie(0); 10 | #define long long long 11 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 12 | const int INF = 1e9+1; 13 | const double EPS = 1e-10; 14 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 15 | void runner(); 16 | int main() { 17 | iostream_optimize(); 18 | int t; 19 | cin >> t; 20 | while(t--) runner(); 21 | } 22 | /* <<<<<<<<<<<<<<<<<<<<<<<<<<<< END TEMPLATE >>>>>>>>>>>>>>>>>>>>>>>>>>> */ 23 | void runner() { 24 | 25 | int n, m; 26 | cin >> n >> m; 27 | 28 | vector D(n+1), mxr(n+1); 29 | vector > A(n+1, vector(m+1)), B(n+1, vector(m+1)); 30 | vector has0(n+1); 31 | vector > cols; 32 | 33 | bool allone = true; 34 | for(int i = 1; i <= n; i++) cin >> D[i], allone &= D[i]; 35 | for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) cin >> A[i][j]; 36 | for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) cin >> B[i][j]; 37 | if(allone) { 38 | cout << "YES\n1 0\n"; 39 | return; 40 | } 41 | for(int col = 1; col <= m; col++) { 42 | bool valid = true; 43 | int mx = 1; 44 | for(int i = 1; i <= n; i++) if(D[i]) { 45 | if(!B[i][col]) valid = false; 46 | mx = max(A[i][col], mx); 47 | } 48 | if(valid) cols.emplace_back(mx, col); 49 | } 50 | sort(cols.begin(), cols.end()); 51 | int T = 1; 52 | for(int idx = 0; idx < cols.size(); idx++) { 53 | int mxt, col; 54 | tie(mxt, col) = cols[idx]; 55 | // cout << "dbg " << mxt << ' ' << col << endl; 56 | T = max(mxt, T); 57 | bool valid = true; 58 | for(int i = 1; i <= n; i++) if(!D[i]) { 59 | if(!B[i][col]) has0[i] = true; 60 | mxr[i] = max(A[i][col], mxr[i]); 61 | valid &= has0[i] || mxr[i] > T; 62 | } 63 | if(valid) { 64 | cout << "YES\n" << T << ' ' << idx+1 << '\n'; 65 | for(int idx2 = 0; idx2 <= idx; idx2++) cout << cols[idx2].second << ' '; 66 | cout << '\n'; 67 | return; 68 | } 69 | } 70 | cout << "NO\n"; 71 | } -------------------------------------------------------------------------------- /CodeForces/CF101149-gym-M.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Divide and conquer 3 | At each node in the segment tree, store the index with maximum value 4 | To maintain this, we only need to make comparisons at non-leaf nodes which will be around n-1 at worst case 5 | To search for second maximum, we binary search on the segments. At each node, we compare the recursively computed second maximum in the child with the global maximum 6 | and the maximum in the child without the maximum (as it will always be less than the maximum) 7 | So, we do one comparison per level, resulting in O(log n) time 8 | 9 | Number of comparisons is n + log(n), which should fit in n + 24 10 | */ 11 | #include 12 | using namespace std; 13 | 14 | int query_cnt; 15 | int query(int i, int j) { 16 | if(i == 0) return -1; 17 | if(j == 0) return 1; 18 | ++query_cnt; 19 | cout << "? " << i << ' ' << j << endl; 20 | string res; 21 | cin >> res; 22 | assert(res != "="); 23 | if(res == "<") return -1; 24 | else return 1; 25 | } 26 | 27 | int f[1 << 14]; 28 | 29 | void rec1(int i, int l, int r) { 30 | if(l == r) { 31 | f[i] = l; 32 | return; 33 | } 34 | int mid = l+r >> 1; 35 | rec1(i << 1, l, mid); 36 | rec1(i << 1 | 1, mid+1, r); 37 | f[i] = (query(f[i << 1], f[i << 1 | 1]) == 1 ? f[i << 1] : f[i << 1 | 1]); 38 | } 39 | 40 | //f[1] = maximum 41 | int rec2(int i, int l, int r) { 42 | if(l == r) { 43 | if(l == f[1]) return 0; 44 | else return f[i]; 45 | } 46 | int mid = l+r >> 1; 47 | int res_left, res_right; 48 | if(l <= f[1] && f[1] <= mid) { 49 | res_left = rec2(i << 1, l, mid); 50 | res_right = f[i << 1 | 1]; 51 | } else { 52 | res_left = f[i << 1]; 53 | res_right = rec2(i << 1 | 1, mid+1, r); 54 | } 55 | return (query(res_left, res_right) == 1 ? res_left : res_right); 56 | } 57 | 58 | int main() { 59 | int n; 60 | cin >> n; 61 | rec1(1, 1, n); 62 | int ans = rec2(1, 1, n); 63 | cout << "! " << ans << endl; 64 | assert(query_cnt <= n + 24); 65 | } 66 | -------------------------------------------------------------------------------- /CodeForces/CF101498-GYM-L.cpp: -------------------------------------------------------------------------------- 1 | //Interesting/Important problem. Got hint that keeping dp[u] is enough. Had to look at another person's code to find bug in Bellman-ford. Turns out that in this version of Bellman-Ford, the condition for negative cycles is a bit different, which cost me a lot of time. Probably better to attack this from an SPFA angle (I don't know it at all). Also, there was a bug with long long, which the problem shouldn't require. Not sure if the test data is wrong or if the problem actually requires long long. 2 | #include 3 | using namespace std; 4 | #define long long long 5 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 6 | const long INF = 1e14; 7 | const double EPS = 1e-10; 8 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 9 | const int N = 2001; 10 | 11 | class TaskL { 12 | int n, m; 13 | vector cnt; 14 | vector dp; 15 | vector > edges; 16 | public: 17 | void solve(istream& cin, ostream& cout) { 18 | int test; 19 | cin >> test; 20 | while(test--) { 21 | cin >> n >> m; 22 | 23 | dp = vector(n+1, 0); 24 | cnt = vector(n+1, 0); 25 | edges.clear(); 26 | 27 | long ans = INF; 28 | for(int i = 0, u, v, w; i < m; i++) { 29 | cin >> u >> v >> w; 30 | edges.emplace_back(u, v, w); 31 | ans = min((long) w, ans); 32 | } 33 | if(ans >= 0) { 34 | cout << ans << '\n'; 35 | continue; 36 | } 37 | 38 | while(ans != -INF && true) { 39 | bool term = false; 40 | for(auto e: edges) { 41 | int u, v, w; 42 | tie(u, v, w) = e; 43 | if(dp[u] + w < dp[v]) { 44 | dp[v] = dp[u] + w; 45 | ++cnt[v]; 46 | term = true; 47 | } 48 | if(cnt[v] > n+1 || dp[v] < -2e9) { 49 | ans = -INF; 50 | term = false; 51 | break; 52 | } 53 | } 54 | if(!term) break; 55 | } 56 | 57 | for(int i = 1; i <= n; i++) ans = min(dp[i], ans); 58 | 59 | if(ans == -INF) cout << "-inf\n"; 60 | else cout << ans << '\n'; 61 | } 62 | } 63 | }; 64 | 65 | int main() { 66 | ios::sync_with_stdio(false); 67 | cin.tie(0); 68 | TaskL solver; 69 | std::istream& in(std::cin); 70 | std::ostream& out(std::cout); 71 | solver.solve(in, out); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /CodeForces/CF101864-GYM-K.cpp: -------------------------------------------------------------------------------- 1 | // if Y is negative, insert one by one and deep delete the other 2 | // if Y is positive, we can do lazy explicit treap 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #define long long long 10 | using namespace std; 11 | 12 | struct item { 13 | long key, prior; 14 | long val, lz; 15 | item *l, *r; 16 | item(long key, long val): key(key), prior(rand()), val(val), lz(0), l(NULL), r(NULL) {} 17 | }; 18 | typedef item* pitem; 19 | pitem root; 20 | 21 | void apply(pitem t) { 22 | if(!t) return; 23 | t->key += t->lz; 24 | if(t->l) t->l->lz += t->lz; 25 | if(t->r) t->r->lz += t->lz; 26 | t->lz = 0; 27 | } 28 | 29 | void split(pitem t, pitem &l, pitem &r, long v) { 30 | apply(t); 31 | if(!t) return void(l = r = NULL); 32 | if(t->key <= v) split(t->r, t->r, r, v), l = t; 33 | else split(t->l, l, t->l, v), r = t; 34 | } 35 | 36 | void merge(pitem &t, pitem l, pitem r) { 37 | apply(l), apply(r); 38 | if(!l || !r) return void(t = l ? l : r); 39 | if(l->prior > r->prior) merge(l->r, l->r, r), t = l; 40 | else merge(r->l, l, r->l), t = r; 41 | } 42 | 43 | void add(pitem &t, pitem x) { 44 | apply(t); 45 | if(!t) t = x; 46 | else if(x->prior > t->prior) split(t, x->l, x->r, x->key), t = x; 47 | else if(x->key < t->key) add(t->l, x); 48 | else add(t->r, x); 49 | } 50 | 51 | 52 | void fill_res(pitem t, vector >& res) { 53 | apply(t); 54 | if(!t) return; 55 | res.emplace_back(t->val, t->key); 56 | fill_res(t->l, res); 57 | fill_res(t->r, res); 58 | } 59 | 60 | void print_answer(pitem root) { 61 | apply(root); 62 | vector > res; 63 | fill_res(root, res); 64 | sort(res.begin(), res.end()); 65 | for(auto p: res) cout << p.second << ' '; 66 | cout << endl; 67 | } 68 | 69 | void apply_all(pitem t, pitem &ins) { 70 | if(!t) return; 71 | apply(t); 72 | add(ins, new item(t->key, t->val)); 73 | apply_all(t->l, ins); 74 | apply_all(t->r, ins); 75 | } 76 | 77 | void deep_delete(pitem t) { 78 | if(!t) return; 79 | deep_delete(t->l); 80 | deep_delete(t->r); 81 | delete t; 82 | } 83 | 84 | int main() { 85 | ios::sync_with_stdio(false); 86 | cin.tie(0); 87 | srand(time(NULL)); 88 | int t; 89 | cin >> t; 90 | while(t--) { 91 | int n, q; 92 | cin >> n >> q; 93 | for(int i = 0, x; i < n; i++) { 94 | cin >> x; 95 | add(root, new item(x, i)); 96 | } 97 | for(int i = 0, tp, x, y; i < q; i++) { 98 | cin >> tp >> x >> y; 99 | if(tp == 1) { 100 | pitem r1, r2; 101 | split(root, r1, r2, x); 102 | if(r1) { 103 | r1->lz -= y; 104 | if(y < 0) { 105 | apply_all(r1, r2); 106 | deep_delete(r1); 107 | root = r2; 108 | } else merge(root, r1, r2); 109 | } else merge(root, r1, r2); 110 | } else { 111 | pitem r1, r2; 112 | split(root, r1, r2, x-1); 113 | if(r2) { 114 | r2->lz += y; 115 | if(y < 0) { 116 | apply_all(r2, r1); 117 | deep_delete(r2); 118 | root = r1; 119 | } else merge(root, r1, r2); 120 | } else merge(root, r1, r2); 121 | } 122 | } 123 | print_answer(root); 124 | deep_delete(root); 125 | root = NULL; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /CodeForces/CF1045-D1-C.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 2e5+1; 4 | 5 | int n, m, q, ccs; 6 | vector g[N], bcg[2*N]; 7 | 8 | int pre[N], lo[N]; 9 | stack stk; 10 | void dfs(int u, int par) { 11 | static int tick = 0; 12 | pre[u] = lo[u] = ++tick; 13 | stk.push(u); 14 | for(int v: g[u]) if(v != par) { 15 | if(!pre[v]) { 16 | dfs(v, u); 17 | lo[u] = min(lo[v], lo[u]); 18 | if(lo[v] >= pre[u]) { 19 | bcg[u].push_back(n + ccs); 20 | while(bcg[n + ccs].empty() || bcg[n + ccs].back() != v) { 21 | bcg[n + ccs].push_back(stk.top()); 22 | stk.pop(); 23 | } 24 | ++ccs; 25 | } 26 | } else { 27 | lo[u] = min(pre[v], lo[u]); 28 | } 29 | } 30 | } 31 | 32 | int d[N], sum[N]; 33 | vector anc[N]; 34 | void init_lca(int u, int par) { 35 | for(int v: bcg[u]) if(v != par) { 36 | d[v] = d[u] + 1; 37 | sum[v] = sum[u] + (v >= n); 38 | anc[v].push_back(u); 39 | for(int j = 0; 1 << j+1 <= d[v]; j++) 40 | anc[v].push_back(anc[anc[v][j]][j]); 41 | init_lca(v, u); 42 | } 43 | } 44 | 45 | int get_lca(int u, int v) { 46 | if(d[u] < d[v]) swap(u, v); 47 | for(int j = 18; j >= 0; j--) if(d[u] - d[v] >> j & 1) u = anc[u][j]; 48 | if(u == v) return u; 49 | for(int j = 18; j >= 0; j--) if(j < anc[u].size() && anc[u][j] != anc[v][j]) 50 | u = anc[u][j], v = anc[v][j]; 51 | return anc[u][0]; 52 | } 53 | 54 | int main() { 55 | ios::sync_with_stdio(false); 56 | cin.tie(0); 57 | cin >> n >> m >> q; 58 | for(int i = 0, u, v; i < m; i++) { 59 | cin >> u >> v; 60 | --u, --v; 61 | g[u].push_back(v); 62 | g[v].push_back(u); 63 | } 64 | dfs(0, -1); 65 | init_lca(0, -1); 66 | for(int i = 0, u, v; i < q; i++) { 67 | cin >> u >> v; 68 | --u, --v; 69 | int lca = get_lca(u, v); 70 | cout << sum[u] + sum[v] - sum[lca] - (lca ? sum[anc[lca][0]] : 0) << '\n'; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /CodeForces/CF149-D2-E.cpp: -------------------------------------------------------------------------------- 1 | // Use KMP to determine how many characters have been matched up so far 2 | #include 3 | using namespace std; 4 | #define long long long 5 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 6 | const int INF = 1e9+1; 7 | const double EPS = 1e-10; 8 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 9 | 10 | 11 | class NewTaskE { 12 | string s, revs; 13 | int m; 14 | 15 | vector match(string s, string t) { 16 | vector f(t.length() + 1); 17 | f[0] = -1; 18 | f[1] = 0; 19 | for(int i = 2; i <= t.length(); i++) { 20 | f[i] = f[i-1]; 21 | while(f[i] != -1 && t[f[i]] != t[i - 1]) f[i] = f[f[i]]; 22 | ++f[i]; 23 | } 24 | vector res; 25 | for(int i = 0, curr = 0; i < s.length(); i++) { 26 | while(curr != -1 && s[i] != t[curr]) curr = f[curr]; 27 | ++curr; 28 | res.push_back(curr); 29 | if(curr == t.length()) curr = f[curr]; 30 | } 31 | return res; 32 | } 33 | 34 | public: 35 | void solve(istream& cin, ostream& cout) { 36 | cin >> s >> m; 37 | revs = s; 38 | reverse(revs.begin(), revs.end()); 39 | int ans = 0; 40 | for(int z = 0; z < m; z++) { 41 | string t, revt; 42 | cin >> t; 43 | if(t.length() == 1) continue; 44 | revt = t; 45 | reverse(revt.begin(), revt.end()); 46 | vector res = match(s, t); 47 | vector res_rev = match(revs, revt); 48 | for(int i = 1; i < res.size(); i++) res[i] = max(res[i-1], res[i]); 49 | for(int i = 1; i < res_rev.size(); i++) res_rev[i] = max(res_rev[i-1], res_rev[i]); 50 | reverse(res_rev.begin(), res_rev.end()); 51 | for(int i = 0; i < res.size()-1; i++) { 52 | // cout << z << ' ' << i << ' ' << res[i] << ' ' << res_rev[i+1] << ' ' << endl; 53 | if(res[i] && res_rev[i+1] && res[i] + res_rev[i+1] >= t.length()) { 54 | ++ans; 55 | break; 56 | } 57 | } 58 | } 59 | cout << ans << endl; 60 | } 61 | }; 62 | 63 | int main() { 64 | ios::sync_with_stdio(false); 65 | cin.tie(0); 66 | NewTaskE solver; 67 | std::istream& in(std::cin); 68 | std::ostream& out(std::cout); 69 | solver.solve(in, out); 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /CodeForces/CF178-D2-F3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * sort strings lexicographically 3 | * divide and conquer 4 | * divide using minimum common prefix and merge with DP 5 | * Can prove that sum of DP over all segments gets runtime O(n^2) 6 | * Need to handle mn value properly to avoid double counting the sum 7 | */ 8 | #include 9 | using namespace std; 10 | #define long long long 11 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 12 | const int INF = 1e9+1; 13 | const double EPS = 1e-10; 14 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 15 | 16 | class NewTaskF { 17 | 18 | int n, k; 19 | vector s; 20 | vector lcp; 21 | 22 | vector rec(int l, int r) { 23 | if(l == r) return vector(2, 0); 24 | vector > down; 25 | int mn = INF; 26 | for(int i = l; i < r; i++) mn = min(lcp[i], mn); 27 | int last = l; 28 | for(int i = l; i < r; i++) if(lcp[i] == mn) { 29 | down.emplace_back(last, i); 30 | last = i+1; 31 | } 32 | down.emplace_back(last, r); 33 | vector dp(min(r-l+1, k) + 1, -LINF); 34 | dp[0] = 0; 35 | for(int i = l; i < r; i++) lcp[i] -= mn; 36 | for(auto p: down) { 37 | vector tmp = rec(p.first, p.second); 38 | for(int kk = dp.size() - 1; kk >= 0; kk--) { 39 | for(int len = 0; len <= min(kk, (int) tmp.size() - 1); len++) { 40 | dp[kk] = max(dp[kk - len] + tmp[len], dp[kk]); 41 | } 42 | } 43 | } 44 | for(int i = l; i < r; i++) lcp[i] += mn; 45 | for(int kk = 0; kk < dp.size(); kk++) dp[kk] += 1ll * mn * kk * (kk - 1) / 2; 46 | return dp; 47 | } 48 | 49 | public: 50 | void solve(istream &cin, ostream &cout) { 51 | cin >> n >> k; 52 | 53 | s.resize(n); 54 | lcp = vector(n); 55 | 56 | for(int i = 0; i < n; i++) cin >> s[i]; 57 | sort(s.begin(), s.end()); 58 | for(int i = 0; i < n-1; i++) { 59 | while(lcp[i] < min(s[i].length(), s[i+1].length()) && s[i][lcp[i]] == s[i+1][lcp[i]]) 60 | ++lcp[i]; 61 | } 62 | vector dp = rec(0, n-1); 63 | cout << dp[k]; 64 | } 65 | }; 66 | 67 | class Solver { 68 | public: 69 | void solve(std::istream& in, std::ostream& out) { 70 | NewTaskF *obj = new NewTaskF(); 71 | obj->solve(in, out); 72 | delete obj; 73 | } 74 | }; 75 | 76 | int main() { 77 | ios::sync_with_stdio(false); 78 | cin.tie(0); 79 | Solver solver; 80 | std::istream& in(std::cin); 81 | std::ostream& out(std::cout); 82 | solver.solve(in, out); 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /CodeForces/CF297-D1-C.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * It's easy to see the if the requirement were n/2 instead of n/3, the problem would be easy. 3 | * It would look like this: 4 | * 0000.... 5 | * ....0000 6 | * 7 | * If s was a permutation, we would fix n/3 duplicates on one side and make the 2n/3 rest unique. 8 | * We also need to make sure that when we split, the values don't intersect (if b[i] != 0 -> b[i] > a[j], where j is in lower segment and i is in upper segment) 9 | * 1 2 3 4 | 5 6 7 8 9 10 11 12 10 | * 0 0 0 0 | 5 1 7 2 9 3 11 4 11 | * 1 2 3 4 | 0 5 0 6 0 7 0 8 12 | * 13 | * Once this has been established, it is easy to extrapolate to a general solution. 14 | * Just change all values of a and b to match for corresponding s[i], except for the _1_2_3_4... in array a. 15 | * That needs to be fixed because its purpose is to make sure that the values don't intersect, and if we matched it, this may not hold anymore. 16 | */ 17 | #include 18 | using namespace std; 19 | #define long long long 20 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 21 | const int INF = 1e9+1; 22 | const double EPS = 1e-10; 23 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 24 | 25 | class TaskC { 26 | int n; 27 | public: 28 | void solve(istream &cin, ostream &cout) { 29 | cin >> n; 30 | vector s(n), a(n), b(n), tmp; 31 | map pos; 32 | for(int i = 0; i < n; i++) { 33 | cin >> s[i]; 34 | tmp.push_back(s[i]); 35 | pos[s[i]] = i; 36 | } 37 | sort(tmp.begin(), tmp.end()); 38 | for(int i = (tmp.size() + 2) / 3; i < n; i += 2) { 39 | a[pos[tmp[i]]] = tmp[i]; 40 | } 41 | for(int i = (tmp.size() + 2) / 3 + 1; i < n; i += 2) { 42 | a[pos[tmp[i]]] = (i - ((tmp.size() + 2) / 3 - 1)) / 2; 43 | } 44 | cout << "YES" << endl; 45 | for(int x: a) cout << x << ' '; 46 | cout << endl; 47 | for(int i = 0; i < n; i++) cout << s[i] - a[i] << ' '; 48 | } 49 | }; 50 | 51 | class Solver { 52 | public: 53 | void solve(std::istream& in, std::ostream& out) { 54 | TaskC *obj = new TaskC(); 55 | obj->solve(in, out); 56 | delete obj; 57 | } 58 | }; 59 | 60 | int main() { 61 | ios::sync_with_stdio(false); 62 | cin.tie(0); 63 | Solver solver; 64 | std::istream& in(std::cin); 65 | std::ostream& out(std::cout); 66 | solver.solve(in, out); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /CodeForces/CF331-D12-C3.cpp: -------------------------------------------------------------------------------- 1 | // Solution notes in iPad 2 | #include 3 | using namespace std; 4 | #define long long long 5 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 6 | const int INF = 1e9+1; 7 | const double EPS = 1e-10; 8 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 9 | 10 | class TaskC { 11 | 12 | map, long> dp, res; 13 | 14 | long calc(long num, long g) { 15 | if(num == 0) return 0; 16 | if(dp.count(make_pair(num, g))) return dp[{num, g}]; 17 | 18 | long lead = num; 19 | while(lead >= 10) lead /= 10; 20 | long lead_p = lead; 21 | while(lead_p <= num) lead_p *= 10; 22 | lead_p /= 10; 23 | 24 | long ret; 25 | if(lead_p == num) { 26 | ret = dp[{num, g}] = calc(max(num - max(g, lead), 0ll), g) + 1; 27 | if(num - max(g, lead) < 0) { 28 | res[{num, g}] = num - max(g, lead); 29 | } else { 30 | res[{num, g}] = res[{max(num - max(g, lead), 0ll), g}]; 31 | } 32 | } else { 33 | assert(num - lead >= 0); 34 | ret = dp[{num, g}] = calc(num - lead_p, max(g, lead)) + calc(lead_p + res[{num - lead_p, max(g, lead)}], g); 35 | res[{num, g}] = res[{lead_p + res[{num - lead_p, max(g, lead)}], g}]; 36 | } 37 | return ret; 38 | } 39 | 40 | int brute(int n) { 41 | vector dp(n+1); 42 | for(int i = 1; i <= n; i++) { 43 | dp[i] = INF; 44 | vector digits; 45 | int tmp = i; 46 | while(tmp) digits.push_back(tmp % 10), tmp /= 10; 47 | for(int d: digits) dp[i] = min(dp[i - d] + 1, dp[i]); 48 | } 49 | return dp[n]; 50 | } 51 | 52 | public: 53 | void solve(istream &cin, ostream &cout) { 54 | long n; 55 | cin >> n; 56 | cout << calc(n, 0) << endl; 57 | } 58 | }; 59 | 60 | class Solver { 61 | public: 62 | void solve(std::istream& in, std::ostream& out) { 63 | TaskC *obj = new TaskC(); 64 | obj->solve(in, out); 65 | delete obj; 66 | } 67 | }; 68 | 69 | int main() { 70 | ios::sync_with_stdio(false); 71 | cin.tie(0); 72 | Solver solver; 73 | std::istream& in(std::cin); 74 | std::ostream& out(std::cout); 75 | solver.solve(in, out); 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /CodeForces/CF38-D12-G.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Binary search for the leftmost index where the suffix maximum is less than a[i] 3 | Use treap to maintain interval maximums in order to support insert oprations 4 | */ 5 | #include 6 | using namespace std; 7 | 8 | struct node { 9 | int cnt, prior; 10 | int val, mx, rightmost; 11 | node *l, *r; 12 | node(int val): cnt(1), prior(rand()), val(val), mx(val), rightmost(val), l(NULL), r(NULL) {} 13 | }; 14 | 15 | typedef node* pnode; 16 | 17 | void update(pnode t) { 18 | if(!t) return; 19 | t->cnt = (t->l ? t->l->cnt : 0) + (t->r ? t->r->cnt : 0) + 1; 20 | if(t->r) t->rightmost = t->r->rightmost; 21 | else t->rightmost = t->val; 22 | t->mx = t->val; 23 | if(t->l) t->mx = max(t->l->mx, t->mx); 24 | if(t->r) t->mx = max(t->r->mx, t->mx); 25 | } 26 | 27 | void split(pnode t, pnode &l, pnode &r, int targ, int add = 0) { 28 | if(!t) return void(l = r = NULL); 29 | int curr_key = add + 1 + (t->l ? t->l->cnt : 0); 30 | if(targ < curr_key) split(t->l, l, t->l, targ, add), r = t; 31 | else split(t->r, t->r, r, targ, curr_key), l = t; 32 | update(t); 33 | } 34 | 35 | void merge(pnode &t, pnode l, pnode r) { 36 | if(!l || !r) return void(t = (l ? l : r)); 37 | if(l->prior > r->prior) merge(l->r, l->r, r), t = l; 38 | else merge(r->l, l, r->l), t = r; 39 | update(t); 40 | } 41 | 42 | int n, rev[100001]; 43 | pnode root; 44 | 45 | void answer(pnode t) { 46 | if(!t) return; 47 | answer(t->l); 48 | cout << rev[t->val] << ' '; 49 | answer(t->r); 50 | } 51 | 52 | int main() { 53 | srand(time(NULL)); 54 | ios::sync_with_stdio(false); 55 | cin.tie(0); 56 | cin >> n; 57 | for(int i = 1, a, c; i <= n; i++) { 58 | cin >> a >> c; 59 | rev[a] = i; 60 | int l = max(i-c, 1), r = i; 61 | pnode p1, p2; 62 | while(l < r) { 63 | int mid = (l+r) >> 1; 64 | split(root, p1, p2, mid-1); 65 | if(p2->mx < a) r = mid; 66 | else l = mid+1; 67 | merge(root, p1, p2); 68 | } 69 | split(root, p1, p2, l-1); 70 | merge(root, p1, new node(a)); 71 | merge(root, root, p2); 72 | } 73 | answer(root); 74 | } 75 | -------------------------------------------------------------------------------- /CodeForces/CF455-D1-E.cpp: -------------------------------------------------------------------------------- 1 | // Notice that a[l] needs to be a minimum. Can prove via contradicton. 2 | // Objective function is s[y] + a[l]*(x-y) + l*a[l] - s[l], y-x+1 <= l <= y 3 | // Use CHT + segtree 4 | #include 5 | #define long long long 6 | using namespace std; 7 | const int N = 1 << 17; 8 | const long LINF = 1e17; 9 | 10 | int n, m; 11 | long a[N], s[N]; 12 | 13 | struct Line { 14 | long m, c; 15 | Line(long m, long c) : m(m), c(c) {} 16 | long get(long x) { return m * x + c; } 17 | long operator<(Line rhs) { return m > rhs.m; } 18 | }; 19 | 20 | struct CHT { 21 | vector stk; 22 | 23 | bool bad(Line l1, Line l2, Line l3) { 24 | return (double) (l1.m-l3.m)*(l2.c-l1.c) >= (double) (l1.m-l2.m)*(l3.c-l1.c); 25 | } 26 | void update(Line v) { 27 | while(stk.size() > 1 && bad(stk[stk.size()-2], stk[stk.size()-1], v)) stk.pop_back(); 28 | stk.push_back(v); 29 | } 30 | long query(long x) { 31 | if(stk.empty()) return LINF; 32 | int l = 0, r = stk.size()-1; 33 | while(r-l > 1) { 34 | int mid = l+r >> 1; 35 | if(stk[mid+1].get(x) <= stk[mid].get(x)) l = mid; 36 | else r = mid; 37 | } 38 | return min(stk[l].get(x), stk[r].get(x)); 39 | } 40 | }; 41 | 42 | CHT t[2*N]; 43 | 44 | void build() { 45 | for(int i = 1; i <= n; i++) t[N+i].update(Line(a[i], 1ll * i * a[i] - s[i])); 46 | for(int i = N-1; i >= 1; i--) { 47 | vector tmp; 48 | merge(t[i << 1].stk.begin(), t[i << 1].stk.end(), t[i << 1 | 1].stk.begin(), t[i << 1 | 1].stk.end(), back_inserter(tmp)); 49 | for(Line v: tmp) t[i].update(v); 50 | } 51 | } 52 | 53 | long query(int l, int r, long x) { 54 | long ret = LINF; 55 | for(l += N, r += N+1; l < r; l >>= 1, r >>= 1) { 56 | if(l & 1) ret = min(t[l++].query(x), ret); 57 | if(r & 1) ret = min(t[--r].query(x), ret); 58 | } 59 | return ret; 60 | } 61 | 62 | int main() { 63 | ios::sync_with_stdio(false); 64 | cin.tie(0); 65 | cin >> n; 66 | for(int i = 1; i <= n; i++) { 67 | cin >> a[i]; 68 | s[i] = s[i-1] + a[i]; 69 | } 70 | build(); 71 | cin >> m; 72 | for(int i = 0, x, y; i < m; i++) { 73 | cin >> x >> y; 74 | long res = s[y] + query(y-x+1, y, x-y); 75 | cout << res << '\n'; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /CodeForces/CF68-D12-D.cpp: -------------------------------------------------------------------------------- 1 | // Main observation is that when we go down the tree, we can cut out one whole subtree. 2 | // This is because the maximum potential when a leaf in the subtree is cut, where the only components are that inside the subtree are considered, 3 | // is bounded by the subtree sum. So, for one of the subtrees, we know the potential of all leaves within the subtree. 4 | #include 5 | using namespace std; 6 | #define long long long 7 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 8 | const int INF = 1e9+1; 9 | const double EPS = 1e-10; 10 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 11 | 12 | class TaskD { 13 | 14 | int h, q; 15 | map f; 16 | 17 | long query(int v, long mx) { 18 | int lg = 32 - __builtin_clz(v); 19 | if(31 - __builtin_clz(v) == h) return max(mx, f[v]); 20 | long ret = 0; 21 | if(f[v << 1] >= f[v << 1 | 1]) { 22 | ret += (1 << h-lg) * max(mx, f[v] - f[v << 1 | 1]); 23 | ret += query(v << 1, max(mx, f[v] - f[v << 1])); 24 | } else { 25 | ret += (1 << h-lg) * max(mx, f[v] - f[v << 1]); 26 | ret += query(v << 1 | 1, max(mx, f[v] - f[v << 1 | 1])); 27 | } 28 | return ret; 29 | } 30 | 31 | public: 32 | void solve(istream &cin, ostream &cout) { 33 | cin >> h >> q; 34 | while(q--) { 35 | string inst; 36 | cin >> inst; 37 | if(inst == "add") { 38 | int v, e; 39 | cin >> v >> e; 40 | while(v >= 1) f[v] += e, v /= 2; 41 | } else { 42 | cout << 1.0 * query(1, 0) / (1 << h) << '\n'; 43 | } 44 | } 45 | } 46 | 47 | }; 48 | 49 | class Solver { 50 | public: 51 | void solve(std::istream& in, std::ostream& out) { 52 | TaskD *obj = new TaskD(); 53 | obj->solve(in, out); 54 | delete obj; 55 | } 56 | }; 57 | 58 | int main() { 59 | ios::sync_with_stdio(false); 60 | cin.tie(0); 61 | Solver solver; 62 | std::istream& in(std::cin); 63 | std::ostream& out(std::cout); 64 | solver.solve(in, out); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /CodeForces/CF704-D1-B.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | dp[i][p] = minimum cost with prefix i and p disjoint paths 3 | Don't count paths containing s and e 4 | If s > e, we can swap them and swap a[i], c[i] and b[i], d[i] 5 | Four cases to consider: 6 | - Create new path 7 | - Append to start of path 8 | - Append to end of path 9 | - Merge paths 10 | Final answer is not dp[n][0] even though it might look like so at first 11 | This is because we never actually merge the path containing s and the path containing e 12 | */ 13 | #include 14 | #define long long long 15 | using namespace std; 16 | const int N = 5010; 17 | const long LINF = 1e17; 18 | 19 | inline void setmin(long &a, long b) { 20 | a = min(a, b); 21 | } 22 | 23 | int n, s, e; 24 | long x[N], a[N], b[N], c[N], d[N]; 25 | long dp[N][N]; 26 | int main() { 27 | ios::sync_with_stdio(false); 28 | cin.tie(0); 29 | cin >> n >> s >> e; 30 | for(int i = 1; i <= n; i++) cin >> x[i]; 31 | for(int i = 1; i <= n; i++) cin >> a[i], a[i] += x[i]; 32 | for(int i = 1; i <= n; i++) cin >> b[i], b[i] -= x[i]; 33 | for(int i = 1; i <= n; i++) cin >> c[i], c[i] += x[i]; 34 | for(int i = 1; i <= n; i++) cin >> d[i], d[i] -= x[i]; 35 | for(int i = 0; i <= n; i++) for(int j = 0; j <= n; j++) dp[i][j] = LINF; 36 | if(s > e) { 37 | for(int i = 1; i <= n; i++) swap(a[i], c[i]), swap(b[i], d[i]); 38 | swap(s, e); 39 | } 40 | dp[0][0] = 0; 41 | for(int i = 0; i < n; i++) { 42 | for(int p = 0; p <= n; p++) { 43 | if(i+1 == s) { 44 | setmin(dp[i+1][p], dp[i][p] + d[i+1]); // new 45 | if(p > 0) setmin(dp[i+1][p-1], dp[i][p] + c[i+1]); // attach 46 | } else if(i+1 == e) { 47 | setmin(dp[i+1][p], dp[i][p] + b[i+1]); // new 48 | if(p > 0) setmin(dp[i+1][p-1], dp[i][p] + a[i+1]); // attach 49 | } else { 50 | setmin(dp[i+1][p+1], dp[i][p] + b[i+1] + d[i+1]); // new 51 | if(i+1 > e || p > 0) setmin(dp[i+1][p], dp[i][p] + c[i+1] + b[i+1]); // append to start 52 | if(i+1 > s || p > 0) setmin(dp[i+1][p], dp[i][p] + a[i+1] + d[i+1]); // append to end 53 | if(p + (i+1 > s) >= 2) setmin(dp[i+1][p-1], dp[i][p] + a[i+1] + c[i+1]); // merge 54 | } 55 | } 56 | } 57 | cout << dp[n-1][0] + a[n] + (e < n ? c[n] : 0); 58 | } 59 | -------------------------------------------------------------------------------- /CodeForces/CF722-D2-E.cpp: -------------------------------------------------------------------------------- 1 | // DP with recurrence based of 559C. Notice that we got down to around lg s to reach s == 1 2 | #include 3 | using namespace std; 4 | #define long long long 5 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 6 | const int INF = 1e9+1; 7 | const double EPS = 1e-10; 8 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 9 | const int N = 2e3+10, M = 2e5+10, K = 31; 10 | 11 | class TaskE { 12 | int n, m, k, s; 13 | vector > a; 14 | long fact[M], invf[M]; 15 | long dp[N][K], paths[N][N], fs[K]; 16 | 17 | long modPow(long b, long e) { 18 | if(e == 0) return 1; 19 | if(e == 1) return b; 20 | return modPow(b*b % MOD, e >> 1) * modPow(b, e & 1) % MOD; 21 | } 22 | 23 | public: 24 | void run(istream &cin, ostream &cout) { 25 | cin >> n >> m >> k >> s; 26 | 27 | fact[0] = 1; 28 | for(int i = 1; i <= n + m; i++) fact[i] = fact[i-1] * i % MOD; 29 | invf[0] = 1; 30 | for(int i = 1; i <= n + m; i++) invf[i] = modPow(fact[i], MOD-2); 31 | fs[0] = s; 32 | for(int i = 1; i < K; i++) fs[i] = fs[i-1] + 1 >> 1; 33 | 34 | a.emplace_back(1, 1); 35 | a.emplace_back(n, m); 36 | for(int i = 0, x, y; i < k; i++) { 37 | cin >> x >> y; 38 | a.emplace_back(x, y); 39 | } 40 | sort(a.begin(), a.end()); 41 | k += 2; 42 | 43 | for(int i = 0; i < k; i++) { 44 | for(int j = 0; j < k; j++) { 45 | int dx = abs(a[i].first - a[j].first); 46 | int dy = abs(a[i].second - a[j].second); 47 | paths[i][j] = fact[dx + dy] * invf[dx] % MOD * invf[dy] % MOD; 48 | } 49 | } 50 | 51 | dp[0][0] = 1; 52 | for(int i = 1; i < k; i++) { 53 | for(int x = 1; x < K; x++) { 54 | for(int j = 0; j < i; j++) if(a[j].first <= a[i].first && a[j].second <= a[i].second) { 55 | dp[i][x] += dp[j][x-1] * paths[i][j] % MOD; 56 | dp[i][x] %= MOD; 57 | } 58 | for(int j = 0; j < i; j++) if(a[j].first <= a[i].first && a[j].second <= a[i].second) { 59 | dp[i][x] -= dp[j][x] * paths[i][j] % MOD; 60 | dp[i][x] = (dp[i][x] % MOD + MOD) % MOD; 61 | } 62 | } 63 | } 64 | long P = 0, sum_less = 0; 65 | for(int x = 1; x < K; x++) { 66 | P += dp[k-1][x] * fs[x-1] % MOD; 67 | sum_less += dp[k-1][x]; 68 | P %= MOD; 69 | sum_less %= MOD; 70 | } 71 | P += paths[0][k-1] - sum_less; 72 | P = (P % MOD + MOD) % MOD; 73 | cout << (P * modPow(paths[0][k-1], MOD-2) % MOD + MOD) % MOD; 74 | } 75 | }; 76 | 77 | class Solver { 78 | public: 79 | void solve(std::istream& in, std::ostream& out) { 80 | TaskE *obj = new TaskE(); 81 | obj->run(in, out); 82 | } 83 | }; 84 | 85 | int main() { 86 | ios::sync_with_stdio(false); 87 | cin.tie(0); 88 | Solver solver; 89 | std::istream& in(std::cin); 90 | std::ostream& out(std::cout); 91 | solver.solve(in, out); 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /CodeForces/CF802-D12-K.cpp: -------------------------------------------------------------------------------- 1 | // dp[v][0] = maximum cost of edges of a connected subgraph within the subtree rooted at v, such that we return back to v afterwards 2 | // dp[v][1] = the same thing but we end up at a vertex in the subtree 3 | // Since we visit a node no more than k times, we go to at most k-1 children (coming back), and one child to not come back (if we choose to) 4 | #include 5 | using namespace std; 6 | #define long long long 7 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 8 | const int INF = 1e9+1; 9 | const double EPS = 1e-10; 10 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 11 | const int N = 1e5+1; 12 | 13 | class TaskK { 14 | 15 | int n, k; 16 | vector > g[N]; 17 | long dp[N][2]; 18 | 19 | void dfs(int u, int par, int pw) { 20 | vector > ls0; 21 | for(auto p: g[u]) { 22 | int v, w; tie(v, w) = p; 23 | if(v == par) continue; 24 | dfs(v, u, w); 25 | ls0.emplace_back(dp[v][0], v); 26 | } 27 | sort(ls0.begin(), ls0.end(), greater >()); 28 | for(int i = 0; i < min(k-1, (int) ls0.size()); i++) dp[u][0] += ls0[i].first; 29 | dp[u][1] = dp[u][0]; 30 | for(int i = 0; i < min(k-1, (int) ls0.size()); i++) 31 | dp[u][1] = max(dp[u][0] - ls0[i].first + dp[ls0[i].second][1] + (ls0.size() > k-1 ? ls0[k-1].first : 0), dp[u][1]); 32 | for(int i = k-1; i < ls0.size(); i++) 33 | dp[u][1] = max(dp[u][0] + dp[ls0[i].second][1], dp[u][1]); 34 | 35 | dp[u][0] += pw, dp[u][1] += pw; 36 | } 37 | 38 | public: 39 | void solve(istream &cin, ostream &cout) { 40 | cin >> n >> k; 41 | for(int i = 1, u, v, w; i < n; i++) { 42 | cin >> u >> v >> w; 43 | g[u].emplace_back(v, w); 44 | g[v].emplace_back(u, w); 45 | } 46 | dfs(0, -1, 0); 47 | cout << dp[0][1]; 48 | } 49 | }; 50 | 51 | class Solver { 52 | public: 53 | void solve(std::istream& in, std::ostream& out) { 54 | TaskK *obj = new TaskK(); 55 | obj->solve(in, out); 56 | delete obj; 57 | } 58 | }; 59 | 60 | int main() { 61 | ios::sync_with_stdio(false); 62 | cin.tie(0); 63 | Solver solver; 64 | std::istream& in(std::cin); 65 | std::ostream& out(std::cout); 66 | solver.solve(in, out); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /CodeForces/CF835-D2-E.cpp: -------------------------------------------------------------------------------- 1 | //Very interesting involving bitmasks of indices. Idea was to check on which bits the indices differ, which can be done with xor queries as it can be observed that at least one bit will differ, from the requirements in the problem. From there, we can find the indices themselves. 2 | #include 3 | using namespace std; 4 | 5 | int n, x, y; 6 | vector odd, even; 7 | 8 | int query(vector S) { 9 | if(S.empty()) return 0; 10 | cout << "? " << S.size() << ' '; 11 | for(int i: S) cout << i << ' '; 12 | cout << endl; 13 | cout.flush(); 14 | int ret; 15 | cin >> ret; 16 | if(ret == -1) exit(0); 17 | return ret; 18 | } 19 | 20 | int query_sup(int i) { 21 | vector S; 22 | for(int mask = 0; mask <= n; mask++) if((mask & i) == i) S.push_back(mask); 23 | int ret = query(S); 24 | return ret == y || ret == (x ^ y); 25 | } 26 | 27 | int main() { 28 | cin >> n >> x >> y; 29 | for(int i = 0; i < 32 - __builtin_clz(n); i++) { 30 | if(query_sup(1 << i)) odd.push_back(i); 31 | else even.push_back(i); 32 | } 33 | int p1 = 1 << odd.back(), p2 = 0; 34 | odd.pop_back(); 35 | for(unsigned int i: odd) { 36 | if(query_sup(p1 | 1 << i)) p1 |= 1 << i; 37 | else p2 |= 1 << i; 38 | } 39 | for(unsigned int i: even) if(query_sup(p1 | 1 << i)) p1 |= 1 << i, p2 |= 1 << i; 40 | if(p1 > p2) swap(p1, p2); 41 | cout << "! " << p1 << ' ' << p2 << endl; 42 | cout.flush(); 43 | } 44 | -------------------------------------------------------------------------------- /CodeForces/CF872-D2-D.cpp: -------------------------------------------------------------------------------- 1 | // Notice that we can find all values of b[0] ^ p[i], p[0] ^ b[i] in 2*n queries 2 | // We also know b[0] ^ p[0], so we can iterate all values of p[0] (or b[0] if you want) and check if the resulting permutations are valid 3 | // The criteria are that p[b[i]] == b[p[i]] == i, all values p[i], b[i] are unique and < n 4 | #include 5 | using namespace std; 6 | 7 | int n, p[5001], b[5001]; 8 | 9 | int query(int i, int j) { 10 | cout << "? " << i << ' ' << j << endl; 11 | int ret; 12 | cin >> ret; 13 | return ret; 14 | } 15 | 16 | int cnt[5001]; 17 | bool eval() { 18 | for(int i = 0; i < n; i++) if(!(b[i] < n && p[i] < n && b[p[i]] == i && p[b[i]] == i)) return false; 19 | fill(cnt, cnt+n, 0); 20 | for(int i = 0; i < n; i++) ++cnt[p[i]]; 21 | for(int i = 0; i < n; i++) if(cnt[i] > 1) return false; 22 | fill(cnt, cnt+n, 0); 23 | for(int i = 0; i < n; i++) ++cnt[b[i]]; 24 | for(int i = 0; i < n; i++) if(cnt[i] > 1) return false; 25 | return true; 26 | } 27 | 28 | int main() { 29 | cin >> n; 30 | for(int i = 0; i < n; i++) { 31 | p[i] = query(i, 0); 32 | b[i] = query(0, i); 33 | } 34 | for(int i = 0; i < n; i++) p[i] ^= b[0]; 35 | int tot = 0; 36 | vector res; 37 | while(p[0] < n) { 38 | if(eval()) { 39 | ++tot; 40 | if(tot == 1) { 41 | for(int i = 0; i < n; i++) res.push_back(p[i]); 42 | } 43 | } 44 | int org_b0 = b[0]; 45 | ++p[0]; 46 | for(int i = 0; i < n; i++) b[i] ^= (p[0] - 1) ^ p[0]; 47 | for(int i = 1; i < n; i++) p[i] ^= org_b0 ^ b[0]; 48 | } 49 | cout << "!\n" << tot << endl; 50 | for(int x: res) cout << x << ' '; 51 | cout << endl; 52 | } 53 | -------------------------------------------------------------------------------- /CodeForces/CF897-D2-D.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Notice that what we're doing here is kind of like an LIS 3 | So use the same algorithm as LIS 4 | This gives at most n*c queries 5 | To reduce to n*c/2, construct the sequence from both the front and the back 6 | */ 7 | #include 8 | using namespace std; 9 | 10 | int n, m, c, cnt_f, cnt_b 11 | vector f, b; 12 | int main() { 13 | cin >> n >> m >> c; 14 | while(m--) { 15 | int x; 16 | cin >> x; 17 | if(x <= c/2) { 18 | auto it = upper_bound(f.begin(), f.end(), x); 19 | cout << it - f.begin() + 1 << endl; 20 | if(it == f.end()) f.push_back(x), ++cnt_f; 21 | else *it = x; 22 | } else { 23 | auto it = upper_bound(b.begin(), b.end(), -x); 24 | cout << n - (it - b.begin()) << endl; 25 | if(it == b.end()) b.push_back(-x), ++cnt_b; 26 | else *it = -x; 27 | } 28 | if(cnt_f + cnt_b == n) return 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CodeForces/CF909-D2-F.cpp: -------------------------------------------------------------------------------- 1 | /* First subtask: 2 | if N is odd, then there is no solution 3 | if p[i] & i is 0, then i is a supermask of p[i] 4 | it follows that we can reverse the order of ~p[i] to p[i] and assign them in that reversed order (see sample 1, when the two endpoints are 1 and 6) 5 | if N is even, we can always decompose consecutive values like this 6 | 7 | Second subtask is from editorial 8 | */ 9 | #include 10 | using namespace std; 11 | #define long long long 12 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 13 | const int INF = 1e9+1; 14 | const double EPS = 1e-10; 15 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 16 | const int N = 1e5+1; 17 | 18 | class TaskF { 19 | int n, p[N], q[N]; 20 | 21 | bool solve1() { 22 | if(n % 2) return false; 23 | iota(p, p + n + 1, 0); 24 | int j = n; 25 | for (int i = n; i >= 1;) { 26 | while (j >= 1 && (i & j)) --j; 27 | assert(j >= 1); 28 | reverse(p + j, p + i + 1); 29 | i = j - 1; 30 | } 31 | return true; 32 | } 33 | 34 | bool solve2() { 35 | if(n < 6 || __builtin_popcount(n) == 1) return false; 36 | if(n == 6) { 37 | vector res = {3, 6, 2, 5, 1, 4}; 38 | for(int i = 0; i < 6; i++) q[i+1] = res[i]; 39 | return true; 40 | } 41 | vector res = {7, 3, 6, 5, 1, 2, 4}; 42 | for(int i = 0; i < 7; i++) q[i+1] = res[i]; 43 | for(int i = 8; i <= n; i <<= 1) { 44 | int j = min((i << 1) - 1, n); 45 | for(int k = i; k <= j; k++) q[k] = k; 46 | for(int k = i; k < j; k++) swap(q[k], q[k+1]); 47 | } 48 | return true; 49 | } 50 | 51 | public: 52 | void solve(istream &cin, ostream &cout) { 53 | cin >> n; 54 | if(solve1()) { 55 | cout << "YES" << endl; 56 | for(int i = 1; i <= n; i++) cout << p[i] << ' ', assert(!(p[i] & i)); 57 | } else cout << "NO"; 58 | cout << endl; 59 | if(solve2()) { 60 | cout << "YES" << endl; 61 | for(int i = 1; i <= n; i++) cout << q[i] << ' ', assert(q[i] & i); 62 | } else cout << "NO"; 63 | } 64 | }; 65 | 66 | class Solver { 67 | public: 68 | void solve(std::istream& in, std::ostream& out) { 69 | TaskF *obj = new TaskF(); 70 | obj->solve(in, out); 71 | delete obj; 72 | } 73 | }; 74 | 75 | int main() { 76 | ios::sync_with_stdio(false); 77 | cin.tie(0); 78 | Solver solver; 79 | std::istream& in(std::cin); 80 | std::ostream& out(std::cout); 81 | solver.solve(in, out); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /CodeForces/CF936-D1-C.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * We'll try to solve this problem using an approach of moving elements from the middle to the extreme indices incrementally 3 | * Denote b = character to move, a = prefix excluding b, c = suffix excluding b, x' as the reverse of substring x 4 | * To move b to the front, we want to go from abc to bac 5 | * To move b to the back, we want to go from abc to acb 6 | * Notice that none of these can be done in three moves (which is the maximum we can do) 7 | * However, notice that c'a'b can be reached within exactly three moves (draw tree of outcomes of all possible three operations) 8 | * By going to c'a'b, we are basically going to bac reversing it after the operation (b' is the same as b) 9 | * However, we are constrained to only move elements to the front, which means we will alternate adding to prefixes and suffixes. 10 | * Solution is to start at the center and incrementally add left and right 11 | * In the end, we reverse the string again if it is still reversed (only happens when n is odd) 12 | */ 13 | #include 14 | using namespace std; 15 | #define long long long 16 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 17 | const int INF = 1e9+1; 18 | const double EPS = 1e-10; 19 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 20 | 21 | class TaskC { 22 | 23 | int n, cntS[26], cntT[26]; 24 | string s, t; 25 | vector ops; 26 | 27 | public: 28 | void solve(istream &cin, ostream &cout) { 29 | 30 | auto shift = [&] (int k) { 31 | ops.push_back(k); 32 | string b = s.substr(n - k, k); 33 | reverse(b.begin(), b.end()); 34 | s = b + s.substr(0, n - k); 35 | }; 36 | 37 | cin >> n >> s >> t; 38 | for(char c: s) ++cntS[c - 'a']; 39 | for(char c: t) ++cntT[c - 'a']; 40 | for(int i = 0; i < 26; i++) if(cntS[i] != cntT[i]) { 41 | cout << -1; 42 | return; 43 | } 44 | int pref = 0, suff = 0; 45 | for(int z = 0; z < n; z++) { 46 | int pos = -1; 47 | if(z % 2 == 0) { 48 | for(int i = pref; i < n - suff; i++) { 49 | if(s[i] == t[(n-1)/2 - z/2]) { 50 | pos = i; 51 | break; 52 | } 53 | } 54 | ++pref; 55 | } else { 56 | for(int i = suff; i < n - pref; i++) { 57 | if(s[i] == t[(n+1)/2 + z/2]) { 58 | pos = i; 59 | break; 60 | } 61 | } 62 | ++suff; 63 | } 64 | if(pos == -1) continue; 65 | shift(n - pos); 66 | shift(n); 67 | shift(n - pos - 1); 68 | } 69 | if(n % 2) shift(n); 70 | cout << ops.size() << '\n'; 71 | for(int k: ops) cout << k << ' '; 72 | } 73 | }; 74 | 75 | class Solver { 76 | public: 77 | void solve(std::istream& in, std::ostream& out) { 78 | TaskC *obj = new TaskC(); 79 | obj->solve(in, out); 80 | delete obj; 81 | } 82 | }; 83 | 84 | int main() { 85 | ios::sync_with_stdio(false); 86 | cin.tie(0); 87 | Solver solver; 88 | std::istream& in(std::cin); 89 | std::ostream& out(std::cout); 90 | solver.solve(in, out); 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /CodeForces/CF939-D2-F.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Notice that in each segment, we don't need to flip more than 2 times 3 | dp[i][j][p] = used i segments with j seconds on side "1" and exiting on side p 4 | 5 | dp[i][j][0] = min(dp[i-1][x][0], dp[i-1][x-y-(l[i] - r[i-1])][1] + 1, dp[i-1][x-y][0] + 2), 0 <= y <= r[i] - l[i] 6 | dp[i][j][1] = min(dp[i-1][x-(r[i]-r[i-1])][1], dp[i-1][x-y][0] + 1, dp[i-1][x-y-(l[i] - r[i-1])][1] + 2) 7 | 8 | Actual limits for x-y-(l[i] - r[i-1]) determined to be [ x+r[i-1]-r[i], x+r[i-1]-l[i] ] 9 | */ 10 | #include 11 | using namespace std; 12 | #define long long long 13 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 14 | const int INF = 1e9+1; 15 | const double EPS = 1e-10; 16 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 17 | const int N = 101, M = 1e5+1; 18 | 19 | struct RMQ { 20 | int n; 21 | vector > t; 22 | RMQ() {} 23 | RMQ(vector vals): n(vals.size()) { 24 | t = vector > (n); 25 | for(int i = 0; i < n; i++) { 26 | t[i].push_back(vals[i]); 27 | for(int j = 0; 1 << j+1 <= i+1; j++) 28 | t[i].push_back(min(t[i][j], t[i - (1 << j)][j])); 29 | } 30 | } 31 | int query(int l, int r) { 32 | if(r < 0 || l > n-1) return INF; 33 | l = max(0, l); 34 | r = min(n-1, r); 35 | int lg = 31 - __builtin_clz(r-l+1); 36 | return min(t[r][lg], t[l + (1 << lg) - 1][lg]); 37 | } 38 | }; 39 | 40 | class TaskF { 41 | 42 | int n, k, l[N], r[N], dp[N][M][2]; 43 | RMQ rmq[2]; 44 | 45 | void setmin(int &a, int b) { a = min(a, b); } 46 | 47 | public: 48 | void solve(istream &cin, ostream &cout) { 49 | cin >> n >> k; 50 | for(int j = 0; j <= n; j++) dp[0][j][0] = dp[0][j][1] = INF; 51 | dp[0][0][0] = 0; 52 | dp[0][0][1] = 0; 53 | for(int i = 1; i <= k; i++) { 54 | cin >> l[i] >> r[i]; 55 | for(int p = 0; p < 2; p++) { 56 | vector vals; 57 | for(int j = 0; j <= n; j++) vals.push_back(dp[i-1][j][p]); 58 | rmq[p] = RMQ(vals); 59 | } 60 | for(int j = 0; j <= n; j++) { 61 | dp[i][j][0] = dp[i][j][1] = INF; 62 | setmin(dp[i][j][0], dp[i-1][j][0]); // no flip 63 | setmin(dp[i][j][0], rmq[1].query(j + r[i-1] - r[i], j + r[i-1] - l[i]) + 1); // one flip 64 | setmin(dp[i][j][0], rmq[0].query(j - (r[i] - l[i]), j) + 2); // two flip 65 | 66 | if(j - (r[i] - r[i-1]) >= 0) setmin(dp[i][j][1], dp[i-1][j - (r[i] - r[i-1])][1]); 67 | setmin(dp[i][j][1], rmq[0].query(j - (r[i] - l[i]), j) + 1); 68 | setmin(dp[i][j][1], rmq[1].query(j - (r[i] - l[i]), j) + 2); 69 | } 70 | } 71 | int ans = min(dp[k][n][0], (r[k] >= n ? dp[k][n - (2*n - r[k])][1] : INF)); 72 | if(ans == INF) cout << "Hungry"; 73 | else cout << "Full\n" << ans; 74 | } 75 | }; 76 | 77 | class Solver { 78 | public: 79 | void solve(std::istream& in, std::ostream& out) { 80 | TaskF *obj = new TaskF(); 81 | obj->solve(in, out); 82 | delete obj; 83 | } 84 | }; 85 | 86 | int main() { 87 | ios::sync_with_stdio(false); 88 | cin.tie(0); 89 | Solver solver; 90 | std::istream& in(std::cin); 91 | std::ostream& out(std::cout); 92 | solver.solve(in, out); 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /Evaluator/o57_apr19_cp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5+10; 4 | 5 | int n, m; 6 | char s[N]; 7 | int sa[N], pos[N], tmp[N], lcp[N], t[2*N]; 8 | set st; 9 | 10 | void buildSA() { 11 | int gap; 12 | auto cmp = [&] (int i, int j) { 13 | if(pos[i] != pos[j]) return pos[i] < pos[j]; 14 | i += gap; 15 | j += gap; 16 | return ((i < N && j < N) ? pos[i] < pos[j] : i > j); 17 | }; 18 | 19 | for(int i = 0; i < n; i++) sa[i] = i, pos[i] = s[i]; 20 | 21 | 22 | for(gap = 1; ; gap <<= 1) { 23 | sort(sa, sa+n, cmp); 24 | for(int i = 1; i < n; i++) tmp[i] = tmp[i-1] + cmp(sa[i-1], sa[i]); 25 | for(int i = 0; i < n; i++) pos[sa[i]] = tmp[i]; 26 | if(tmp[n-1] == n-1) break; 27 | } 28 | } 29 | 30 | void buildLCP() { 31 | for(int i = 0, k = 0; i < n; i++, k = (k ? k-1 : 0)) { 32 | if(pos[i] == n-1) { 33 | k = 0; 34 | continue; 35 | } 36 | int j = sa[pos[i] + 1]; 37 | while(i + k < n && j + k < n && s[i + k] == s[j + k]) ++k; 38 | lcp[pos[i]] = k; 39 | } 40 | } 41 | 42 | int query(int l, int r) { 43 | int ret = INT_MAX; 44 | for(l += n, r += n + 1; l < r; l >>= 1, r >>= 1) { 45 | if(l & 1) ret = min(t[l++], ret); 46 | if(r & 1) ret = min(t[--r], ret); 47 | } 48 | return ret; 49 | } 50 | 51 | int main() { 52 | ios::sync_with_stdio(false); 53 | cin.tie(0); 54 | cin >> n >> m >> s; 55 | buildSA(); 56 | buildLCP(); 57 | for(int i = 0; i < n; i++) t[i + n] = lcp[i]; 58 | for(int i = n-1; i >= 1; i--) t[i] = min(t[i << 1], t[i << 1 | 1]); 59 | st.insert(pos[0]); 60 | for(int i = 0, inst, idx; i < m; i++) { 61 | cin >> inst >> idx; 62 | --idx; 63 | idx = pos[idx]; 64 | if(inst == 1) { 65 | st.insert(idx); 66 | } else { 67 | auto it = st.lower_bound(idx); 68 | if(it != st.end() && *it == idx) { 69 | cout << n - sa[idx] << '\n'; 70 | continue; 71 | } 72 | int res = 0; 73 | if(it != st.end()) { 74 | res = max(query(idx, *it - 1), res); 75 | } 76 | if(it != st.begin()) { 77 | it = prev(it); 78 | res = max(query(*it, idx - 1), res); 79 | } 80 | cout << res << '\n'; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Evaluator/o57_apr26_orepi.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Divide and conquer optimization 3 | */ 4 | #include 5 | using namespace std; 6 | #define long long long 7 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 8 | const int INF = 1e9+1; 9 | const double EPS = 1e-10; 10 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 11 | const int N = 40100; 12 | 13 | class Orepi { 14 | int n, m; 15 | long a[N], s[N], dp[110][N]; 16 | 17 | void rec(int i, int l, int r, int optL, int optR) { 18 | if(l > r) return; 19 | int mid = l + r >> 1; 20 | int opt = optL; 21 | for(int j = optL; j <= min(optR, mid-1); j++) { 22 | if(dp[i-1][j] + (s[mid] - s[j]) * (mid - j) < dp[i][mid]) { 23 | dp[i][mid] = dp[i-1][j] + (s[mid] - s[j]) * (mid - j); 24 | opt = j; 25 | } 26 | } 27 | rec(i, l, mid-1, optL, opt); 28 | rec(i, mid+1, r, opt, optR); 29 | } 30 | 31 | public: 32 | void solve(istream &cin, ostream &cout) { 33 | cin >> n >> m; 34 | ++m; 35 | for(int i = 1; i <= n; i++) { 36 | cin >> a[i]; 37 | s[i] = s[i-1] + a[i]; 38 | } 39 | if(m >= n) { 40 | cout << s[n] << endl; 41 | return; 42 | } 43 | for(int i = 0; i <= m; i++) for(int j = 0; j <= n; j++) 44 | dp[i][j] = LINF; 45 | dp[0][0] = 0; 46 | for(int i = 1; i <= m; i++) { 47 | rec(i, 1, n, 0, n-1); 48 | } 49 | cout << dp[m][n] << endl; 50 | } 51 | }; 52 | 53 | class Solver { 54 | public: 55 | void solve(std::istream& in, std::ostream& out) { 56 | Orepi *obj = new Orepi(); 57 | obj->solve(in, out); 58 | delete obj; 59 | } 60 | }; 61 | 62 | int main() { 63 | ios::sync_with_stdio(false); 64 | cin.tie(0); 65 | Solver solver; 66 | std::istream& in(std::cin); 67 | std::ostream& out(std::cout); 68 | solver.solve(in, out); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /Evaluator/o58_apr23_hiking.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | const int N = 2e5+10; 9 | 10 | class Hiking { 11 | 12 | int n, m, L; 13 | vector g[N]; 14 | int dist[N], trace[N]; 15 | vector s; 16 | bool on_path[N]; 17 | 18 | void bfs() { 19 | queue q; 20 | fill(dist, dist+N, INF); 21 | q.push(1); 22 | dist[1] = 0; 23 | while(!q.empty()) { 24 | int u = q.front(); 25 | q.pop(); 26 | for(int v: g[u]) { 27 | if(dist[u] + 1 < dist[v]) { 28 | dist[v] = dist[u] + 1; 29 | trace[v] = u; 30 | q.push(v); 31 | } 32 | } 33 | } 34 | for(int v = n; v >= 1; v = trace[v]) on_path[v] = true; 35 | } 36 | 37 | int pre[N], low[N]; 38 | stack stk; 39 | void dfs1(int u, int p) { 40 | static int tick = 0; 41 | pre[u] = low[u] = ++tick; 42 | stk.push(u); 43 | stable_partition(g[u].begin(), g[u].end(), [&] (int i) { return on_path[i]; }); // need to do this or else not using BFS order will get condition low[v] >= pre[trace[v]] mixed up in traceback 44 | for(int v: g[u]) { 45 | if(v == p) continue; 46 | if(!pre[v]) { 47 | dfs1(v, u); 48 | low[u] = min(low[v], low[u]); 49 | } else { 50 | low[u] = min(pre[v], low[u]); 51 | } 52 | } 53 | } 54 | 55 | public: 56 | void solve(istream &cin, ostream &cout) { 57 | cin >> n >> m >> L; 58 | for(int i = 0, u, v; i < m; i++) { 59 | cin >> u >> v; 60 | g[u].push_back(v); 61 | g[v].push_back(u); 62 | } 63 | bfs(); 64 | dfs1(1, -1); 65 | for(int v = n; v != 1; v = trace[v]) { 66 | if(trace[v] != 1 && trace[v] != n) { 67 | if(low[v] >= pre[trace[v]]) { 68 | s.push_back(dist[trace[v]]); 69 | } 70 | } 71 | } 72 | reverse(s.begin(), s.end()); 73 | 74 | int ans = 0, curr = 0; 75 | while(true) { 76 | auto it = lower_bound(s.begin(), s.end(), curr); 77 | if(it == s.end()) break; 78 | ++ans; 79 | curr = *it + 2*L + 1; 80 | } 81 | cout << ans << endl; 82 | } 83 | }; 84 | 85 | class Solver { 86 | public: 87 | void solve(std::istream& in, std::ostream& out) { 88 | Hiking *obj = new Hiking(); 89 | obj->solve(in, out); 90 | delete obj; 91 | } 92 | }; 93 | 94 | int main() { 95 | ios::sync_with_stdio(false); 96 | cin.tie(0); 97 | Solver solver; 98 | std::istream& in(std::cin); 99 | std::ostream& out(std::cout); 100 | solver.solve(in, out); 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /Evaluator/o58_apr25_convexways.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define long long long 3 | using namespace std; 4 | const int N = 2010; 5 | const long INF = 1e7+1; 6 | 7 | struct vec { 8 | long x, y; 9 | vec() { x = y = INF; } 10 | vec(long x, long y): x(x), y(y) {} 11 | long operator^(const vec& rhs) const { 12 | return x * rhs.y - y * rhs.x; 13 | } 14 | vec operator-(const vec& rhs) const { 15 | return vec(x - rhs.x, y - rhs.y); 16 | } 17 | bool operator==(const vec& rhs) const { 18 | return x == rhs.x && y == rhs.y; 19 | } 20 | }; 21 | 22 | int n, ans; 23 | vec pt[N]; 24 | 25 | vector g[N]; 26 | bool adj[N][N]; 27 | 28 | bool valid[N][N]; 29 | int pre[N][N]; 30 | 31 | void dfs1(int u, int src, int second, vec last) { 32 | for(int v: g[u]) { 33 | if(v == pre[src][u]) continue; 34 | pre[src][v] = u; 35 | 36 | if(last == vec(INF, INF)) { 37 | valid[src][v] = true; 38 | second = v; 39 | } else { 40 | valid[src][v] = valid[src][u]; 41 | valid[src][v] &= (last ^ (pt[v] - pt[u])) < 0; 42 | valid[src][v] &= ((pt[v] - pt[pre[src][v]]) ^ (pt[src] - pt[v])) < 0; 43 | valid[src][v] &= ((pt[src] - pt[v]) ^ (pt[second] - pt[src])) < 0; 44 | // cerr << src << ' ' << u << ' ' <> n; 55 | for(int i = 0, x, y; i < n; i++) { 56 | cin >> x >> y; 57 | pt[i] = vec(x, y); 58 | valid[i][i] = true; 59 | } 60 | for(int i = 1, u, v; i < n; i++) { 61 | cin >> u >> v; 62 | --u, --v; 63 | g[u].push_back(v); 64 | g[v].push_back(u); 65 | adj[u][v] = adj[v][u] = true; 66 | } 67 | for(int i = 0; i < n; i++) { 68 | pre[i][i] = -1; 69 | dfs1(i, i, -1, vec(INF, INF)); 70 | } 71 | for(int i = 0; i < n; i++) { 72 | for(int j = 0; j < n; j++) { 73 | if(i == j || adj[i][j]) continue; 74 | ans += valid[i][j]; 75 | // if(valid[i][j]) cerr << i << ' ' << j << endl; 76 | } 77 | } 78 | cout << ans << endl; 79 | } 80 | -------------------------------------------------------------------------------- /Evaluator/o58_apr27_landwall.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define long int64_t 3 | using namespace std; 4 | const int N = 1001, INF = 1e9+1; 5 | 6 | int n, k, ans, a[N], dp[N][N], mx[N]; 7 | 8 | int main() { 9 | ios::sync_with_stdio(false); 10 | cin.tie(0); 11 | cin >> n >> k; 12 | for(int i = 1; i <= n; i++) cin >> a[i]; 13 | 14 | for(int i = 0; i <= n; i++) for(int j = 0; j <= k; j++) dp[i][j] = -INF; 15 | for(int j = 0; j <= k; j++) mx[j] = -INF; 16 | 17 | mx[0] = 0; 18 | dp[1][0] = a[1]; 19 | ans = max(a[1], ans); 20 | 21 | for(int i = 2; i <= n; i++) { 22 | dp[i][0] = mx[0] + a[i]; 23 | for(int j = 1; j <= k; j++) { 24 | dp[i][j] = max(dp[i-1][j-1], mx[j]) + a[i]; 25 | } 26 | for(int j = 0; j <= k; j++) { 27 | if(dp[i][j] < 0) dp[i][j] = -INF; 28 | ans = max(dp[i][j], ans); 29 | // cerr << i << ' ' << j << ' ' << dp[i][j] << endl; 30 | } 31 | for(int j = 0; j <= k; j++) { 32 | mx[j] = max(dp[i-1][j], mx[j]); 33 | } 34 | } 35 | cout << ans << endl; 36 | } 37 | -------------------------------------------------------------------------------- /Evaluator/o58_apr30_citrus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | const int N = 101; 9 | 10 | class Citrus { 11 | 12 | int n, k, S[N], A[N][N], B[N]; 13 | int dp[N][N][N]; 14 | 15 | inline void setmin(int &a, int b) { 16 | a = min(a, b); 17 | } 18 | 19 | public: 20 | void solve(istream &cin, ostream &cout) { 21 | cin >> n >> k; 22 | for(int i = 0; i < n; i++) { 23 | cin >> S[i]; 24 | --S[i]; 25 | } 26 | for(int i = 0; i < k; i++) { 27 | for(int j = 0; j < k; j++) { 28 | cin >> A[i][j]; 29 | if(i == j) A[i][j] = 0; 30 | } 31 | } 32 | for(int x = 0; x < k; x++) { 33 | for(int i = 0; i < k; i++) { 34 | for(int j = 0; j < k; j++) { 35 | A[i][j] = min(A[i][x] + A[x][j], A[i][j]); 36 | } 37 | } 38 | } 39 | for(int i = 0; i < k; i++) cin >> B[i]; 40 | 41 | memset(dp, -1, sizeof(dp)); 42 | for(int i = 0; i < n; i++) { 43 | for(int j = 0; j < k; j++) { 44 | dp[i][i][j] = A[S[i]][j]; 45 | } 46 | } 47 | for(int len = 2; len <= n; len++) { 48 | for(int l = 0; l < n - len + 1; l++) { 49 | int r = l + len - 1; 50 | for(int x = 0; x < k; x++) { 51 | dp[l][r][(x + 1) % k] = INF; 52 | for(int i = l; i < r; i++) { 53 | // cerr << "compute_nxt " << l << ' ' << r << ' ' << x << ' ' << dp[l][i][x] << ' ' << dp[i+1][r][x] << ' ' << B[x] << ' ' << dp[l][i][x] + dp[i+1][r][x] + B[x] << endl; 54 | setmin(dp[l][r][(x+1) % k], dp[l][i][x] + dp[i+1][r][x] + B[x]); 55 | } 56 | } 57 | for(int x = 0; x < k; x++) { 58 | for(int y = 0; y < k; y++) { 59 | setmin(dp[l][r][y], dp[l][r][x] + A[x][y]); 60 | } 61 | } 62 | // for(int x = 0; x < k; x++) { 63 | // cerr << "Actual " << l << ' ' << r << ' ' << x << ' ' << dp[l][r][x] << endl; 64 | // } 65 | } 66 | } 67 | int ans = *min_element(dp[0][n-1], dp[0][n-1] + k); 68 | cout << ans << endl; 69 | } 70 | }; 71 | 72 | class Solver { 73 | public: 74 | void solve(std::istream& in, std::ostream& out) { 75 | Citrus *obj = new Citrus(); 76 | obj->solve(in, out); 77 | delete obj; 78 | } 79 | }; 80 | 81 | int main() { 82 | ios::sync_with_stdio(false); 83 | cin.tie(0); 84 | Solver solver; 85 | std::istream& in(std::cin); 86 | std::ostream& out(std::cout); 87 | solver.solve(in, out); 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /Evaluator/o59_may05_pointsonstrip.cpp: -------------------------------------------------------------------------------- 1 | #include "pointlib.h" 2 | #include 3 | using namespace std; 4 | const int N = 3010, M = 2e6+10, INF = 1e9; 5 | 6 | int n, d[N][N], x[N], y[N], id[M][2]; 7 | vector ord, so_far; 8 | 9 | inline int dist(int x1, int y1, int x2, int y2) { 10 | return abs(x1 - x2) + abs(y1 - y2); 11 | } 12 | 13 | bool rec(int idx, int tx, int ty, int mnx, int mxx) { 14 | mnx = min(tx, mnx); 15 | mxx = max(tx, mxx); 16 | 17 | if(mxx - mnx > 1000000 || id[tx][ty] != -INF) return false; 18 | 19 | int i = ord[idx]; 20 | bool valid = true; 21 | for(int j: so_far) if(dist(tx, ty, x[j], y[j]) != d[i][j]) { 22 | valid = false; 23 | break; 24 | } 25 | if(!valid) return false; 26 | // cerr << "valid " << ord[idx] << ' ' << tx << ' ' << ty << endl; 27 | // cerr << "stack" << endl; 28 | // for(int i: ord) cerr << i << ' ' << x[i] << ' ' << y[i] << endl; 29 | // cerr << endl; 30 | 31 | so_far.push_back(i); 32 | id[tx][ty] = i; 33 | x[i] = tx, y[i] = ty; 34 | 35 | if(idx == n-1) return true; 36 | 37 | int nxt = ord[idx + 1]; 38 | 39 | bool ret = false; 40 | ret |= rec(idx + 1, M/2 + d[0][nxt], 0, mnx, mxx); 41 | if(!ret) ret |= rec(idx + 1, M/2 - d[0][nxt], 0, mnx, mxx); 42 | if(!ret) ret |= rec(idx + 1, M/2 + d[0][nxt] - 1, 1, mnx, mxx); 43 | if(!ret) ret |= rec(idx + 1, M/2 + 1 - d[0][nxt], 1, mnx, mxx); 44 | 45 | if(!ret) { 46 | so_far.pop_back(); 47 | id[tx][ty] = -INF; 48 | x[i] = y[i] = -INF; 49 | } 50 | 51 | return ret; 52 | } 53 | 54 | int main() { 55 | fill(x, x+N, -INF); 56 | fill(y, y+N, -INF); 57 | for(int i = 0; i < M; i++) id[i][0] = id[i][1] = -INF; 58 | n = point_init(); 59 | for(int i = 0; i < n; i++) { 60 | for(int j = 0; j < n; j++) { 61 | d[i][j] = query(i, j); 62 | } 63 | } 64 | for(int i = 0; i < n; i++) ord.push_back(i); 65 | sort(ord.begin(), ord.end(), [] (int i, int j) { return d[0][i] < d[0][j]; }); 66 | rec(0, M/2, 0, M/2, 0); 67 | 68 | int mx_x = *max_element(x, x+n); 69 | if(mx_x > 1000000) { 70 | for(int i = 0; i < n; i++) x[i] -= mx_x - 1000000; 71 | } 72 | 73 | for(int i = 0; i < n; i++) { 74 | assert(0 <= x[i] && x[i] <= 1000000); 75 | assert(0 <= y[i] && y[i] <= 1); 76 | for(int j = 0; j < n; j++) { 77 | assert(dist(x[i], y[i], x[j], y[j]) == d[i][j]); 78 | } 79 | } 80 | 81 | for(int i = 0; i < n; i++) printf("%d %d\n", x[i], y[i]); 82 | } 83 | -------------------------------------------------------------------------------- /Evaluator/o60_may10_parade.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | const int N = 1e5+1; 9 | 10 | class Parade { 11 | 12 | long modPow(long b, long e) { 13 | if(e == 0) return 1; 14 | if(e == 1) return b; 15 | return modPow(b*b % MOD, e >> 1) * modPow(b, e & 1) % MOD; 16 | } 17 | 18 | int n; 19 | vector g[N]; 20 | long fact[N], invf[N]; 21 | 22 | int sz[N]; 23 | long ans, dp[N]; 24 | 25 | void dfs1(int u, int p) { 26 | sz[u] = 1; 27 | if(p >= 0) g[u].erase(find(g[u].begin(), g[u].end(), p)); 28 | for(int v: g[u]) { 29 | dfs1(v, u); 30 | sz[u] += sz[v]; 31 | } 32 | dp[u] = fact[sz[u] - 1]; 33 | for(int v: g[u]) { 34 | dp[u] *= dp[v] * invf[sz[v]] % MOD; 35 | dp[u] %= MOD; 36 | } 37 | // cerr << u << ' ' << dp[u] << endl; 38 | } 39 | 40 | void dfs2(int u) { 41 | // cerr << "answer " << u << ' ' << dp[u] << endl; 42 | ans = (ans + dp[u]) % MOD; 43 | for(int v: g[u]) { 44 | long org_dp_u = dp[u], org_dp_v = dp[v], org_sz_u = sz[u], org_sz_v = sz[v]; 45 | dp[u] = dp[u] * fact[sz[v]] % MOD * modPow(dp[v], MOD - 2) % MOD; 46 | dp[u] = dp[u] * fact[sz[u] - sz[v] - 1] % MOD * invf[sz[u] - 1] % MOD; 47 | sz[u] -= sz[v]; 48 | dp[v] = dp[v] * dp[u] % MOD * invf[sz[u]] % MOD; 49 | dp[v] = dp[v] * fact[sz[v] + sz[u] - 1] % MOD * invf[sz[v] - 1] % MOD; 50 | sz[v] += sz[u]; 51 | // cerr << dp[u] << ' ' << sz[u] << ' ' << dp[v] << ' ' << sz[v] << endl; 52 | dfs2(v); 53 | dp[u] = org_dp_u; 54 | dp[v] = org_dp_v; 55 | sz[u] = org_sz_u; 56 | sz[v] = org_sz_v; 57 | } 58 | } 59 | 60 | public: 61 | void solve(istream &cin, ostream &cout) { 62 | cin >> n; 63 | for(int i = 1, u, v; i < n; i++) { 64 | cin >> u >> v; 65 | g[u].push_back(v); 66 | g[v].push_back(u); 67 | } 68 | fact[0] = invf[0] = 1; 69 | for(int i = 1; i <= n; i++) { 70 | fact[i] = fact[i-1] * i % MOD; 71 | invf[i] = modPow(fact[i], MOD - 2); 72 | } 73 | dfs1(0, -1); 74 | dfs2(0); 75 | cout << ans << endl; 76 | } 77 | }; 78 | 79 | class Solver { 80 | public: 81 | void solve(std::istream& in, std::ostream& out) { 82 | Parade *obj = new Parade(); 83 | obj->solve(in, out); 84 | delete obj; 85 | } 86 | }; 87 | 88 | int main() { 89 | ios::sync_with_stdio(false); 90 | cin.tie(0); 91 | Solver solver; 92 | std::istream& in(std::cin); 93 | std::ostream& out(std::cout); 94 | solver.solve(in, out); 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /Evaluator/o61_mar_c1_cycletax.cpp: -------------------------------------------------------------------------------- 1 | //https://www.cs.princeton.edu/courses/archive/fall03/cs528/handouts/two_stremlined.pdf 2 | #include 3 | using namespace std; 4 | const int INF = 1e9+1; 5 | const int N = 1010; 6 | 7 | int n, m, S, T; 8 | vector g[N]; 9 | vector > edges; 10 | 11 | int tick, pre[N], low[N]; 12 | void dfs1(int u, int p) { 13 | pre[u] = ++tick; 14 | low[u] = u; 15 | for(int v: g[u]) { 16 | if(v == p) continue; 17 | if(pre[v]) { 18 | if(pre[v] < pre[low[u]]) low[u] = v; 19 | continue; 20 | } 21 | dfs1(v, u); 22 | if(pre[low[v]] < pre[low[u]]) low[u] = low[v]; 23 | } 24 | // cerr << u << ' ' << low[u] << endl; 25 | } 26 | 27 | bool mark[N]; 28 | list::iterator it[N]; 29 | list L; 30 | void dfs2(int u) { 31 | mark[u] = true; 32 | for(int v: g[u]) { 33 | if(mark[v]) continue; 34 | if(v == T) { 35 | L.push_back(T); 36 | it[T] = prev(L.end()); 37 | } else { 38 | if(*it[low[v]] < 0) { 39 | it[v] = L.insert(it[u], v); 40 | *it[u] = u; 41 | } else { 42 | it[v] = L.insert(next(it[u]), v); 43 | *it[u] = -u; 44 | } 45 | } 46 | // cerr << "curr " << u << ' ' << v << endl; 47 | // for(int x: L) cerr << x << ' '; 48 | // cerr << endl; 49 | dfs2(v); 50 | } 51 | } 52 | 53 | int main() { 54 | ios::sync_with_stdio(false); 55 | cin.tie(0); 56 | cin >> n >> m; 57 | int mn = INF; 58 | for(int i = 0, u, v, c; i < m; i++) { 59 | cin >> u >> v >> c; 60 | if(c < mn) { 61 | S = u; 62 | T = v; 63 | mn = c; 64 | } 65 | g[u].push_back(v); 66 | g[v].push_back(u); 67 | edges.emplace_back(u, v); 68 | } 69 | for(int &v: g[S]) if(v == T) swap(v, g[S][0]); 70 | L.push_back(-S); 71 | it[S] = prev(L.end()); 72 | dfs1(S, 0); 73 | dfs2(S); 74 | 75 | vector ord; 76 | copy(L.begin(), L.end(), back_inserter(ord)); 77 | vector rev(n+1); 78 | for(int i = 0; i < ord.size(); i++) { 79 | rev[abs(ord[i])] = i; 80 | } 81 | 82 | cout << mn << ' ' << 1 << '\n'; 83 | for(auto e: edges) { 84 | int u, v; 85 | tie(u, v) = e; 86 | if(rev[v] < rev[u]) swap(u, v); 87 | if(u == S && v == T) cout << v << ' ' << u << ' ' << 1 << '\n'; 88 | else cout << u << ' ' << v << ' ' << 0 << '\n'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Evaluator/o61_mar_c1_pyramid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 5010; 4 | 5 | int f[2*N][2*N]; 6 | void update(int x, int y) { 7 | assert(x >= 0 && y >= 0); 8 | ++x, ++y; 9 | for(int i = x; i < 2*N; i += i & -i) 10 | for(int j = y; j < 2*N; j += j & -j) 11 | ++f[i][j]; 12 | } 13 | int query(int x, int y) { 14 | ++x, ++y; 15 | int ret = 0; 16 | for(int i = x; i > 0; i -= i & -i) 17 | for(int j = y; j > 0; j -= j & -j) 18 | ret += f[i][j]; 19 | return ret; 20 | } 21 | 22 | int main() { 23 | ios::sync_with_stdio(false); 24 | cin.tie(0); 25 | int n; 26 | cin >> n; 27 | for(int i = 0, x, h; i < n; i++) { 28 | cin >> x >> h; 29 | cout << query(2*N-2, N+x-h) - query(x+h-1, N+x-h) << '\n'; 30 | update(x + h, N + x - h); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Evaluator/o61_mar_c1_salary.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5+1; 4 | 5 | int n, a[N]; 6 | vector g[N]; 7 | multiset f[N]; 8 | void dfs(int u) { 9 | for(int v: g[u]) { 10 | dfs(v); 11 | if(f[v].size() > f[u].size()) swap(f[u], f[v]); 12 | for(int x: f[v]) f[u].insert(x); 13 | f[v].clear(); 14 | } 15 | auto it = f[u].upper_bound(a[u]); 16 | if(it == f[u].end()) f[u].insert(a[u]); 17 | else { 18 | f[u].erase(it); 19 | f[u].insert(a[u]); 20 | } 21 | } 22 | 23 | int main() { 24 | ios::sync_with_stdio(false); 25 | cin.tie(0); 26 | cin >> n; 27 | for(int i = 0, x; i < n; i++) cin >> a[i]; 28 | for(int i = 1, u, v; i < n; i++) { 29 | cin >> u >> v; 30 | g[u].push_back(v); 31 | } 32 | dfs(0); 33 | cout << n - f[0].size() << endl; 34 | } 35 | -------------------------------------------------------------------------------- /Evaluator/o61_mar_c1_traffic.cpp: -------------------------------------------------------------------------------- 1 | #include "traffic.h" 2 | #include 3 | using namespace std; 4 | 5 | int n, k; 6 | vector xs, ys; 7 | vector > ans; 8 | int ax1, ay1, ax2, ay2, bx1, by1, bx2, by2; 9 | int main() { 10 | traffic_init(&n, &k); 11 | for(int i = 1; i <= n; i++) { 12 | if(traffic_query(i, 1, i, n) > n-1) 13 | xs.push_back(i); 14 | } 15 | for(int i = 1; i <= n; i++) { 16 | if(traffic_query(1, i, n, i) > n-1) 17 | ys.push_back(i); 18 | } 19 | for(int x: xs) { 20 | int l = 2, r = n; 21 | while(l < r) { 22 | int mid = l+r >> 1; 23 | if(traffic_query(x, 1, x, mid) > mid-1) r = mid; 24 | else l = mid+1; 25 | } 26 | ans.emplace_back(x, l-1, x, l); 27 | if(k == 2 && xs.size() + ys.size() == 1) { 28 | int l = 2, r = n; 29 | while(l < r) { 30 | int mid = l+r >> 1; 31 | if(traffic_query(x, 1, x, mid) > mid) r = mid; 32 | else l = mid+1; 33 | } 34 | ans.emplace_back(x, l-1, x, l); 35 | } 36 | } 37 | for(int y: ys) { 38 | int l = 2, r = n; 39 | while(l < r) { 40 | int mid = l+r >> 1; 41 | if(traffic_query(1, y, mid, y) > mid-1) r = mid; 42 | else l = mid+1; 43 | } 44 | ans.emplace_back(l-1, y, l, y); 45 | if(k == 2 && xs.size() + ys.size() == 1) { 46 | int l = 2, r = n; 47 | while(l < r) { 48 | int mid = l+r >> 1; 49 | if(traffic_query(1, y, mid, y) > mid) r = mid; 50 | else l = mid+1; 51 | } 52 | ans.emplace_back(l-1, y, l, y); 53 | } 54 | } 55 | tie(ax1, ay1, ax2, ay2) = ans[0]; 56 | if(k == 2) 57 | tie(bx1, by1, bx2, by2) = ans[1]; 58 | traffic_report(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2); 59 | } 60 | -------------------------------------------------------------------------------- /Evaluator/o61_oct_c1_charprint.cpp: -------------------------------------------------------------------------------- 1 | // Use element of that character at the smallest index 2 | // Handle mode 1 using fenwick trees 3 | #include 4 | using namespace std; 5 | const int N = 3e5+1; 6 | 7 | int n, m, mode; 8 | string s, t; 9 | priority_queue, greater > pq[26]; 10 | 11 | int f[N]; 12 | void update(int i, int v) { 13 | ++i; 14 | while(i < N) f[i] += v, i += i & -i; 15 | } 16 | int query(int i) { 17 | ++i; 18 | int ret = 0; 19 | while(i > 0) ret += f[i], i -= i & -i; 20 | return ret; 21 | } 22 | 23 | int main() { 24 | ios::sync_with_stdio(false); 25 | cin.tie(0); 26 | cin >> mode >> s >> t; 27 | n = s.length(), m = t.length(); 28 | for(int i = 0; i < n; i++) { 29 | pq[s[i] - 'a'].push(i); 30 | update(i, 1); 31 | } 32 | long ans = 0; 33 | for(int i = 0; i < m; i++) { 34 | if(pq[t[i] - 'a'].empty()) cout << -1, exit(0); 35 | ans += query(pq[t[i] - 'a'].top()); 36 | update(pq[t[i] - 'a'].top(), -mode); 37 | pq[t[i] - 'a'].pop(); 38 | } 39 | cout << ans; 40 | } 41 | -------------------------------------------------------------------------------- /Evaluator/o61_oct_c1_knives.cpp: -------------------------------------------------------------------------------- 1 | // Consider the height at maximum width for each blade. For each query, we can compute the width at the given height if we have the height at maximum width, since the difference is always going up/down by one. 2 | // After we find the formula, we can see that it is easily maintainable using a fenwick tree. 3 | #include 4 | #define long long long 5 | using namespace std; 6 | const int N = 1 << 20; 7 | 8 | struct fenwick { 9 | long f[N]; 10 | void update(int i, int v) { ++i; while(i < N) f[i] += v, i += i & -i; } 11 | long query(int i) { 12 | ++i; 13 | long ret = 0; 14 | while(i > 0) ret += f[i], i -= i & -i; 15 | return ret; 16 | } 17 | long query(int l, int r) { 18 | return query(r) - query(l-1); 19 | } 20 | } cnt[2]; 21 | 22 | int n; 23 | long L, Q, mnidx[N], mxidx[N], sum[2]; 24 | bool state[N]; 25 | 26 | inline long get_mxidx(int i) { 27 | return (state[i] ? mnidx[i] : mxidx[i]); 28 | } 29 | 30 | int main() { 31 | ios::sync_with_stdio(false); 32 | cin.tie(0); 33 | cin >> n >> L >> Q; 34 | sum[0] = L * n; 35 | cnt[0].update(L, n); 36 | for(int i = 0; i < n; i++) mxidx[i] = L; 37 | for(int t = 0; t < Q; t++) { 38 | char inst; 39 | long a, b; 40 | cin >> inst >> a; 41 | if(inst == 's' || inst == 'f') { 42 | cnt[state[a]].update(get_mxidx(a), -1); 43 | sum[state[a]] -= get_mxidx(a); 44 | if(inst == 's') { 45 | cin >> b; 46 | mxidx[a] = (mxidx[a] + b - 1) % L + 1; 47 | mnidx[a] = (mnidx[a] + b) % L; 48 | } else state[a] ^= 1; 49 | cnt[state[a]].update(get_mxidx(a), 1); 50 | sum[state[a]] += get_mxidx(a); 51 | } else { 52 | long res = 0; 53 | res += cnt[0].query(a, L) * L + cnt[0].query(0, L) * a - sum[0]; 54 | res += cnt[1].query(0, a) * L + sum[1] - cnt[1].query(0, L) * a; 55 | cout << res <<'\n'; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Evaluator/o61_oct_c2_longpipe.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define long long long 3 | using namespace std; 4 | const int MOD = 1e9+7; 5 | 6 | struct matrix { 7 | vector > a; 8 | matrix() { a = vector >(6, vector(6)); } 9 | matrix operator*(matrix rhs) { 10 | matrix ret = matrix(); 11 | for(int i = 0; i < 6; i++) for(int j = 0; j < 6; j++) for(int k = 0; k < 6; k++) { 12 | ret.a[i][j] += a[i][k] * rhs.a[k][j] % MOD; 13 | ret.a[i][j] %= MOD; 14 | } 15 | return ret; 16 | } 17 | } bases[31]; 18 | 19 | struct vec { 20 | vector a; 21 | vec() { a = vector(6); } 22 | vec operator*(matrix rhs) { 23 | vec ret = vec(); 24 | for(int i = 0; i < 6; i++) for(int j = 0; j < 6; j++) { 25 | ret.a[i] += rhs.a[i][j] * a[j] % MOD; 26 | ret.a[i] %= MOD; 27 | } 28 | return ret; 29 | } 30 | }; 31 | 32 | int main() { 33 | int n; 34 | cin >> n; 35 | matrix A = matrix(); 36 | A.a[0] = {2, 1, 0, -1, -1, 1}; 37 | A.a[1] = {1, 2, 1, -1, -1, -1}; 38 | A.a[2] = {0, 1, 2, 1, -1, -1}; 39 | for(int i = 0; i < 3; i++) A.a[i+3][i] = 1; 40 | 41 | bases[0] = A; 42 | for(int j = 1; j <= 30; j++) bases[j] = bases[j-1] * bases[j-1]; 43 | 44 | vec ans = vec(); 45 | for(int i = 0; i < 3; i++) ans.a[i] = 1; 46 | for(int j = 30; j >= 0; j--) if(n >> j & 1) { 47 | ans = ans * bases[j]; 48 | } 49 | cout << ((ans.a[0] + ans.a[1] + ans.a[2] - ans.a[3] - ans.a[4] - ans.a[5]) % MOD + MOD) % MOD; 50 | } 51 | -------------------------------------------------------------------------------- /Evaluator/o62_mar_c1_flat2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5+1, INF = 1e9; 4 | 5 | int n, w, a[N], t[2*N], lb[N], rb[N], ans[N]; 6 | 7 | int query(int l, int r) { 8 | int res = INF; 9 | for(l += n, r += n+1; l < r; l >>= 1, r >>= 1) { 10 | if(l & 1) res = min(t[l++], res); 11 | if(r & 1) res = min(t[--r], res); 12 | } 13 | return res; 14 | } 15 | 16 | int main() { 17 | ios::sync_with_stdio(false); 18 | cin.tie(0); 19 | cin >> n >> w; 20 | memset(ans, -1, sizeof(ans)); 21 | for(int i = 0; i < n; i++) { 22 | cin >> a[i]; 23 | t[n+i] = a[i]; 24 | } 25 | for(int i = n-1; i >= 1; i--) t[i] = min(t[i << 1], t[i << 1 | 1]); 26 | for(int i = 0; i < n; i++) { 27 | int l = 0, r = i; 28 | while(l < r) { 29 | int mid = l+r >> 1; 30 | if(query(mid, i) >= a[i]) r = mid; 31 | else l = mid + 1; 32 | } 33 | lb[i] = l; 34 | l = i, r = n-1; 35 | while(l < r) { 36 | int mid = l+r+1 >> 1; 37 | if(query(i, mid) >= a[i]) l = mid; 38 | else r = mid-1; 39 | } 40 | rb[i] = l; 41 | ans[rb[i] - lb[i]] = max(a[i], ans[rb[i] - lb[i]]); 42 | // cout << i << ' ' << lb[i] << ' ' << rb[i] << endl; 43 | } 44 | if(w > 0) cout << ans[w] << endl; 45 | else { 46 | for(int i = 1; i <= n; i++) cout << ans[i] << ' '; 47 | cout << endl; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Evaluator/o62_mar_c1_socks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sockslib.h" 3 | using namespace std; 4 | const int N = 2010; 5 | 6 | int n, nxt[N], rev_nxt[N]; 7 | bool matched[N]; 8 | int main() { 9 | n = num(); 10 | n *= 2; 11 | nxt[n] = n + 1; 12 | for(int i = n-1; i >= 1; i--) { 13 | int l = i, r = n; 14 | while(l < r) { 15 | int mid = l+r+1 >> 1; 16 | vector v; 17 | for(int j = i; j <= mid; j++) { 18 | if(!matched[j]) v.push_back(j); 19 | } 20 | if(ask(v) == v.size()) l = mid; 21 | else r = mid-1; 22 | } 23 | nxt[i] = l+1; 24 | if(nxt[i] > n) continue; 25 | int j = l; 26 | while(nxt[j] != l+1) --j; 27 | vector tmp = {i, j}; 28 | match(l + 1, j); 29 | matched[l + 1] = matched[j] = true; 30 | nxt[l + 1] = -1; 31 | nxt[j] = -1; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Evaluator/o62_mar_c2_blind.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 3e5+1; 4 | 5 | struct info { 6 | int inst, a, b, c; 7 | info(int inst, int a, int b, int c): inst(inst), a(a), b(b), c(c) {} 8 | }; 9 | 10 | int n, m, dsu[N]; 11 | vector requests; 12 | vector g[N], ls[N]; 13 | int indeg[N]; 14 | vector ord; 15 | 16 | int root(int v) { return (dsu[v] < 0 ? v : dsu[v] = root(dsu[v])); } 17 | 18 | void merge(int u, int v) { 19 | if((u = root(u)) == (v = root(v))) return; 20 | dsu[u] += dsu[v]; 21 | dsu[v] = u; 22 | } 23 | 24 | int main() { 25 | ios::sync_with_stdio(false); 26 | cin.tie(0); 27 | cin >> n >> m; 28 | memset(dsu, -1, sizeof(dsu)); 29 | for(int i = 0, inst, a, b, c; i < m; i++) { 30 | cin >> inst >> a >> b >> c; 31 | if(inst == 3) { 32 | merge(a, b); 33 | merge(b, c); 34 | } else { 35 | requests.emplace_back(inst, a, b, c); 36 | } 37 | } 38 | for(info curr: requests) { 39 | curr.a = root(curr.a); 40 | curr.b = root(curr.b); 41 | curr.c = root(curr.c); 42 | if(curr.inst == 1) { 43 | g[curr.a].push_back(curr.b); 44 | g[curr.a].push_back(curr.c); 45 | ++indeg[curr.b]; 46 | ++indeg[curr.c]; 47 | } else { 48 | g[curr.b].push_back(curr.a); 49 | g[curr.c].push_back(curr.a); 50 | indeg[curr.a] += 2; 51 | } 52 | } 53 | queue q; 54 | for(int i = 1; i <= n; i++) if(root(i) == i && !indeg[i]) q.push(i); 55 | while(!q.empty()) { 56 | int u = q.front(); 57 | q.pop(); 58 | ord.push_back(u); 59 | for(int v: g[u]) { 60 | --indeg[v]; 61 | if(!indeg[v]) q.push(v); 62 | } 63 | } 64 | for(int i = 1; i <= n; i++) ls[root(i)].push_back(i); 65 | reverse(ord.begin(), ord.end()); 66 | 67 | cout << ord.size() << '\n'; 68 | for(int x: ord) { 69 | cout << ls[x].size() << ' '; 70 | for(int i: ls[x]) cout << i << ' '; 71 | cout << '\n'; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Evaluator/o62_mar_c2_outoforder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5+1; 4 | 5 | int n, a[N], d[N]; 6 | vector ls[N]; 7 | long ans; 8 | 9 | int f[N]; 10 | void update(int i) { 11 | while(i <= n) ++f[i], i += i & -i; 12 | } 13 | 14 | int query(int i) { 15 | int res = 0; 16 | while(i > 0) res += f[i], i -= i & -i; 17 | return res; 18 | } 19 | 20 | int main() { 21 | ios::sync_with_stdio(false); 22 | cin.tie(0); 23 | cin >> n; 24 | for(int i = 1; i <= n; i++) { 25 | cin >> a[i]; 26 | ls[a[i]].push_back(i); 27 | assert(1 <= a[i] && a[i] <= n); 28 | } 29 | for(int i = 1; i <= n; i++) cin >> d[i]; 30 | for(int x = 1; x <= n; x++) { 31 | for(int i: ls[x]) { 32 | // cerr << x << ' ' << i << endl; 33 | ans += query(min(i + d[i], n)) - query(i); 34 | // cerr << query(min(i + d[i], n)) << ' ' << query(i) << endl; 35 | } 36 | for(int i: ls[x]) { 37 | update(i); 38 | } 39 | } 40 | memset(f, 0, sizeof(f)); 41 | for(int x = n; x >= 1; x--) { 42 | for(int i: ls[x]) { 43 | ans += query(i) - query(max(i - d[i], 1) - 1); 44 | } 45 | for(int i: ls[x]) { 46 | update(i); 47 | } 48 | } 49 | cout << ans << endl; 50 | } 51 | -------------------------------------------------------------------------------- /Evaluator/o62_may07_bts.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 3001, M = 1001, INF = 1e9+1; 4 | 5 | int n, m, A, B, cnt_between, f[M][M], dp[M][M]; 6 | vector > edges; 7 | 8 | vector xs; 9 | void compress() { 10 | sort(xs.begin(), xs.end()); 11 | xs.resize(unique(xs.begin(), xs.end()) - xs.begin()); 12 | for(int i = 0, u, v, w; i < m; i++) { 13 | tie(u, v, w) = edges[i]; 14 | get<0>(edges[i]) = lower_bound(xs.begin(), xs.end(), u) - xs.begin(); 15 | get<1>(edges[i]) = lower_bound(xs.begin(), xs.end(), v) - xs.begin(); 16 | } 17 | assert(xs.size() < M); 18 | } 19 | 20 | int main() { 21 | cin >> n >> m >> A >> B; 22 | if(A > B) swap(A, B); 23 | for(int i = 0, u, v, w; i < m; i++) { 24 | cin >> u >> v >> w; 25 | if(u > v) swap(u, v); 26 | if(w <= A) { 27 | cout << -1 << endl; 28 | return 0; 29 | } 30 | edges.emplace_back(u, v, w); 31 | xs.push_back(u); 32 | xs.push_back(v); 33 | cnt_between += w <= B; 34 | } 35 | if(cnt_between == 0) { 36 | cout << 1ll * B * (n - 1) << endl; 37 | return 0; 38 | } 39 | compress(); 40 | for(int i = 0, u, v, w; i < m; i++) { 41 | tie(u, v, w) = edges[i]; 42 | for(int x = u; x >= 0; x--) { 43 | for(int y = v; y < xs.size(); y++) { 44 | ++f[x][y]; 45 | } 46 | } 47 | } 48 | 49 | for(int k = 0; k <= m; k++) for(int r = 0; r < xs.size(); r++) { 50 | dp[k][r] = INF; 51 | } 52 | 53 | int res = INF; 54 | dp[0][0] = 0; 55 | 56 | for(int k = 0; k <= m; k++) { 57 | for(int r = 1; r < xs.size(); r++) { 58 | dp[k][r] = min(dp[k][r-1], dp[k][r]); 59 | for(int l = r-1; l >= 0; l--) { 60 | if(f[l][r] > k) continue; 61 | dp[k][r] = min(dp[k - f[l][r]][l] + xs[r] - xs[l], dp[k][r]); 62 | } 63 | if(k >= cnt_between) res = min(dp[k][r], res); 64 | } 65 | } 66 | cout << 1ll * A * res + 1ll * B * (n - 1 - res) << endl; 67 | } 68 | -------------------------------------------------------------------------------- /Evaluator/o62_may07_camp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define long long long 3 | using namespace std; 4 | const int N = 6e5+1; 5 | 6 | int n, orgl[N], orgr[N], orgw[N]; 7 | long ans, dp[N][2]; 8 | vector > ls[N]; 9 | 10 | vector xs; 11 | void preprocess() { 12 | sort(xs.begin(), xs.end()); 13 | xs.resize(unique(xs.begin(), xs.end()) - xs.begin()); 14 | assert(xs.size() == n * 2); 15 | for(int i = 0; i < n; i++) { 16 | orgr[i] = lower_bound(xs.begin(), xs.end(), orgr[i]) - xs.begin(); 17 | orgl[i] = lower_bound(xs.begin(), xs.end(), orgl[i]) - xs.begin(); 18 | ls[orgr[i]].emplace_back(orgl[i], orgw[i]); 19 | } 20 | } 21 | 22 | struct SegmentTree { 23 | long t[2*N]; 24 | void update(int i, long v) { 25 | for(t[i += N] = v; i > 1; i >>= 1) t[i>>1] = max(t[i], t[i^1]); 26 | } 27 | 28 | long query(int l, int r) { 29 | long res = 0; 30 | for(l += N, r += N+1; l < r; l >>= 1, r >>= 1) { 31 | if(l & 1) res = max(t[l++], res); 32 | if(r & 1) res = max(t[--r], res); 33 | } 34 | return res; 35 | } 36 | } st1, st2; 37 | 38 | void solve_large() { 39 | for(int r = 0; r < xs.size(); r++) { 40 | if(r) { 41 | dp[r][0] = dp[r-1][0]; 42 | dp[r][1] = dp[r-1][1]; 43 | } 44 | long mxw = 0; 45 | for(auto tt: ls[r]) { 46 | long l, w; 47 | tie(l, w) = tt; 48 | mxw = max(w, mxw); 49 | dp[r][0] = max((l ? dp[l][0] : 0) + w, dp[r][0]); 50 | dp[r][1] = max((l ? dp[l][1] : 0) + w, dp[r][1]); 51 | dp[r][1] = max(st1.query(l, r) + w, dp[r][1]); 52 | dp[r][1] = max((l ? dp[l][0] : 0) + st2.query(l, r) + w, dp[r][1]); 53 | } 54 | st1.update(r, dp[r][0]); 55 | st2.update(r, mxw); 56 | ans = max(max(dp[r][0], dp[r][1]), ans); 57 | } 58 | } 59 | 60 | int main() { 61 | cin >> n; 62 | for(int i = 0; i < n; i++) { 63 | cin >> orgl[i] >> orgr[i] >> orgw[i]; 64 | xs.push_back(orgr[i]); 65 | xs.push_back(orgl[i]); 66 | } 67 | preprocess(); 68 | solve_large(); 69 | cout << ans << endl; 70 | } 71 | -------------------------------------------------------------------------------- /Evaluator/o62_may07_marathon.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 5e4+1, RAND_LIM = 95, INF = 1e9+1; 4 | 5 | int n, S, T, m, Q, dist[RAND_LIM][N]; 6 | vector > g[N]; 7 | vector ss, tt; 8 | bool iss[N], ist[N]; 9 | 10 | void dijkstra(int s, int dist[]) { 11 | fill(dist, dist + n + 1, INF); 12 | priority_queue > pq; 13 | dist[s] = 0; 14 | pq.emplace(-dist[s], s); 15 | while(!pq.empty()) { 16 | int u = pq.top().second; 17 | pq.pop(); 18 | for(auto p: g[u]) { 19 | int v, w; 20 | tie(v, w) = p; 21 | if(dist[u] + w < dist[v]) { 22 | dist[v] = dist[u] + w; 23 | pq.emplace(-dist[v], v); 24 | } 25 | } 26 | } 27 | } 28 | 29 | int main() { 30 | srand(1000); 31 | ios::sync_with_stdio(false); 32 | cin.tie(0); 33 | cin >> n >> S >> T >> m >> Q; 34 | for(int i = 0, u, v, w; i < m; i++) { 35 | cin >> u >> v >> w; 36 | g[u].emplace_back(v, w); 37 | g[v].emplace_back(u, w); 38 | } 39 | for(int i = 0, v; i < S; i++) { 40 | cin >> v; 41 | ss.push_back(v); 42 | iss[v] = true; 43 | } 44 | for(int i = 0, v; i < T; i++) { 45 | cin >> v; 46 | tt.push_back(v); 47 | ist[v] = true; 48 | } 49 | vector candidates; 50 | for(int i = 1; i <= n; i++) { 51 | if(iss[i] || ist[i]) continue; 52 | candidates.push_back(i); 53 | } 54 | random_shuffle(candidates.begin(), candidates.end()); 55 | for(int i = 0; i < min((int) candidates.size(), RAND_LIM); i++) { 56 | dijkstra(candidates[i], dist[i]); 57 | } 58 | for(int i = 0, u, v; i < Q; i++) { 59 | cin >> u >> v; 60 | int res = INF; 61 | for(int w = 0; w < min((int) candidates.size(), RAND_LIM); w++) { 62 | res = min(dist[w][u] + dist[w][v], res); 63 | } 64 | cout << res << '\n'; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Evaluator/o62_may09_parent.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5+1; 4 | 5 | struct info { 6 | int op, u, v; 7 | info(int op, int u, int v): op(op), u(u), v(v) {} 8 | }; 9 | 10 | struct DSU { 11 | int f[N], master[N]; 12 | DSU() { 13 | fill(f, f + N, -1); 14 | for(int i = 0; i < N; i++) master[i] = i; 15 | } 16 | int root(int v) { 17 | return (f[v] < 0 ? v : f[v] = root(f[v])); 18 | } 19 | int find_master(int v) { 20 | return master[root(v)]; 21 | } 22 | void change_master(int v) { 23 | master[root(v)] = v; 24 | } 25 | void merge(int u, int v) { 26 | swap(u, v); 27 | if((u = root(u)) == (v = root(v))) { 28 | assert(false); 29 | return; 30 | } 31 | f[u] += f[v]; 32 | f[v] = u; 33 | } 34 | } dsu; 35 | 36 | int n, m; 37 | vector ops; 38 | vector g[N]; 39 | 40 | int d[N]; 41 | vector anc[N]; 42 | bool mark[N]; 43 | void init_dfs(int u, int p) { 44 | mark[u] = true; 45 | for(int v: g[u]) { 46 | if(v == p) continue; 47 | d[v] = d[u] + 1; 48 | anc[v].push_back(u); 49 | for(int j = 0; 1 << j+1 <= d[v]; j++) { 50 | anc[v].push_back(anc[anc[v][j]][j]); 51 | } 52 | init_dfs(v, u); 53 | } 54 | } 55 | 56 | int get_lca(int u, int v) { 57 | if(d[u] < d[v]) swap(u, v); 58 | int diff = d[u] - d[v]; 59 | for(int j = 0; j < 19; j++) { 60 | if(diff >> j & 1) u = anc[u][j]; 61 | } 62 | if(u == v) return u; 63 | for(int j = anc[u].size() - 1; j >= 0; j--) { 64 | if(j < anc[u].size() && anc[u][j] != anc[v][j]) { 65 | u = anc[u][j]; 66 | v = anc[v][j]; 67 | } 68 | } 69 | return anc[u][0]; 70 | } 71 | 72 | int main() { 73 | ios::sync_with_stdio(false); 74 | cin.tie(0); 75 | cin >> n >> m; 76 | for(int i = 0; i < m; i++) { 77 | info tmp(-1, -1, -1); 78 | cin >> tmp.op >> tmp.u; 79 | if(tmp.op != 2) cin >> tmp.v; 80 | ops.push_back(tmp); 81 | } 82 | for(int i = 0; i < m; i++) { 83 | if(ops[i].op == 1) { 84 | g[ops[i].u].push_back(ops[i].v); 85 | g[ops[i].v].push_back(ops[i].u); 86 | } 87 | } 88 | for(int i = 1; i <= n; i++) { 89 | if(!mark[i]) init_dfs(i, -1); 90 | } 91 | init_dfs(1, -1); 92 | for(int i = 0; i < m; i++) { 93 | if(ops[i].op == 1) { 94 | dsu.merge(ops[i].u, ops[i].v); // order is very important here 95 | } else if(ops[i].op == 2) { 96 | dsu.change_master(ops[i].u); 97 | } else { 98 | int master = dsu.find_master(ops[i].u); 99 | assert(dsu.find_master(ops[i].v) == master); 100 | int lca_u = get_lca(ops[i].u, master); 101 | int lca_v = get_lca(ops[i].v, master); 102 | bool isU = d[ops[i].u] + d[master] - 2*d[lca_u] < d[ops[i].v] + d[master] - 2*d[lca_v]; 103 | cout << (isU ? ops[i].u : ops[i].v) << '\n'; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Evaluator/o62_may11_insert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 2e5 + 1; 4 | 5 | int n, a[N]; 6 | char sign[N]; 7 | long pref[N], pref_abs[N], ans; 8 | vector subs; 9 | int main() { 10 | ios::sync_with_stdio(false); 11 | cin.tie(0); 12 | cin >> n; 13 | sign[1] = '+'; 14 | for(int i = 0; i < 2*n - 1; i++) { 15 | if (i % 2) cin >> sign[i / 2 + 2]; 16 | else cin >> a[i / 2 + 1]; 17 | } 18 | for(int i = 1; i <= n; i++) { 19 | pref[i] = pref[i-1] + a[i] * (sign[i] == '+' ? 1 : -1); 20 | pref_abs[i] = pref_abs[i-1] + a[i]; 21 | if(sign[i] == '-') { 22 | subs.push_back(i); 23 | } 24 | } 25 | long ans = pref[n]; 26 | for(int i = 1; i < subs.size(); i++) { 27 | long s1 = pref[subs[i-1] - 1]; 28 | long s2 = pref_abs[subs[i] - 1] - pref_abs[subs[i-1] - 1]; 29 | long s3 = pref_abs[n] - pref_abs[subs[i] - 1]; 30 | ans = max(s1 - s2 + s3, ans); 31 | } 32 | cout << ans << endl; 33 | } 34 | -------------------------------------------------------------------------------- /Evaluator/o62_may15_repeats.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n, k; 5 | string s; 6 | int main() { 7 | ios::sync_with_stdio(false); 8 | cin.tie(0); 9 | cin >> k >> s; 10 | n = s.length(); 11 | int ans = 0; 12 | for(int gap = 2; gap <= n; gap += 2) { 13 | int curr_diff = 0; 14 | for(int i = 0; i < gap / 2; i++) { 15 | curr_diff += s[i] != s[i + gap / 2]; 16 | } 17 | if(curr_diff <= k) ++ans; 18 | for(int i = 1; i + gap - 1 < n; i++) { 19 | curr_diff -= s[i - 1] != s[i - 1 + gap / 2]; 20 | curr_diff += s[i + gap - 1] != s[i + gap / 2 - 1]; 21 | if(curr_diff <= k) ++ans; 22 | } 23 | } 24 | cout << ans << endl; 25 | } 26 | -------------------------------------------------------------------------------- /Evaluator/o62_may15_triquery.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 6e3+100, M = 2e3 + 100, shift = 2010; 4 | 5 | int n, m, a[N][N]; 6 | struct fenwick { 7 | int f2d[N][M]; 8 | 9 | void update_2d(int x, int y, int add) { 10 | x += shift; 11 | for(int i = x; i < N; i += i & -i) { 12 | for(int j = y; j < M; j += j & -j) { 13 | f2d[i][j] += add; 14 | } 15 | } 16 | } 17 | 18 | int query_2d(int x, int y) { 19 | x += shift; 20 | int ret = 0; 21 | for(int i = x; i > 0; i -= i & -i) { 22 | for(int j = y; j > 0; j -= j & -j) { 23 | ret += f2d[i][j]; 24 | } 25 | } 26 | return ret; 27 | } 28 | int query_box(int x1, int y1, int x2, int y2) { 29 | return query_2d(x2, y2) - query_2d(x1 - 1, y2) - query_2d(x2, y1 - 1) + query_2d(x1 - 1, y1 - 1); 30 | } 31 | } fen1, fen2; 32 | 33 | int main() { 34 | ios::sync_with_stdio(false); 35 | cin.tie(0); 36 | cin >> n >> m; 37 | for(int i = 0, inst, R, C, X; i < m; i++) { 38 | cin >> inst >> R >> C >> X; 39 | if(inst == 1) { 40 | --X; 41 | int res1 = fen1.query_box(R + C - X, 1, R + C, M - 1); 42 | int res2 = fen1.query_box(R + C - X, R + 1, R + C, M - 1); 43 | int res3 = fen2.query_box(R + C - X, C + 1, R + C, M - 1); 44 | int res4 = fen1.query_box(R + C - X, 1, R + C - X, M - 1) - fen1.query_box(R + C - X, R + 1, R + C - X, M - 1) - fen2.query_box(R + C - X, C + 1, R + C - X, M - 1); 45 | cout << res1 - res2 - res3 - res4 / 2 << '\n'; 46 | } else { 47 | fen1.update_2d(R + C, R, X - a[R][C]); 48 | fen2.update_2d(R + C, C, X - a[R][C]); 49 | a[R][C] = X; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Evaluator/o62_may16_fanclub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define long long long 3 | using namespace std; 4 | const int N = 2e5+10; 5 | const long LINF = 1e17; 6 | 7 | int n, m, A, B; 8 | vector > g[N]; 9 | 10 | vector tmp, scaffold; 11 | long S[N]; 12 | bool in_path[N]; 13 | int rev[N]; 14 | void dfs_scaffold(int u, int par) { 15 | tmp.push_back(u); 16 | if(u == B) { 17 | for(int i = 0; i < tmp.size(); i++) { 18 | rev[tmp[i]] = i; 19 | scaffold.push_back(tmp[i]); 20 | in_path[tmp[i]] = true; 21 | } 22 | } 23 | for(auto p: g[u]) { 24 | int v, w; 25 | tie(v, w) = p; 26 | if(v == par) continue; 27 | S[v] = S[u] + w; 28 | dfs_scaffold(v, u); 29 | } 30 | tmp.pop_back(); 31 | } 32 | 33 | long sub[N]; 34 | long dfs_subtree(int u, int par, int src) { 35 | long ret = 0; 36 | for(auto p: g[u]) { 37 | int v, w; 38 | tie(v, w) = p; 39 | if(v == par || in_path[v]) continue; 40 | long tmp = dfs_subtree(v, u, src); 41 | ret = max(tmp + w, ret); 42 | } 43 | return ret; 44 | } 45 | 46 | long t[2*N], vl[2*N], vr[2*N]; 47 | 48 | void build() { 49 | for(int i = 0; i < scaffold.size(); i++) { 50 | t[scaffold.size() + i] = -LINF; 51 | vl[scaffold.size() + i] = sub[scaffold[i]] - S[scaffold[i]]; 52 | vr[scaffold.size() + i] = sub[scaffold[i]] + S[scaffold[i]]; 53 | } 54 | for(int i = scaffold.size() - 1; i >= 1; i--) { 55 | t[i] = max(t[i << 1], t[i << 1 | 1]); 56 | t[i] = max(vl[i << 1] + vr[i << 1 | 1], t[i]); 57 | vl[i] = max(vl[i << 1], vl[i << 1 | 1]); 58 | vr[i] = max(vr[i << 1], vr[i << 1 | 1]); 59 | } 60 | } 61 | 62 | long query(int l, int r) { 63 | long ret = -LINF; 64 | vector nodes_l, nodes_r, nodes; 65 | for(l += scaffold.size(), r += scaffold.size() + 1; l < r; l >>= 1, r >>= 1) { 66 | if(l & 1) nodes_l.push_back(l++); 67 | if(r & 1) nodes_r.push_back(--r); 68 | } 69 | nodes = nodes_l; 70 | reverse(nodes_r.begin(), nodes_r.end()); 71 | for(int i: nodes_r) nodes.push_back(i); 72 | long mxl = -LINF; 73 | for(int i: nodes) { 74 | ret = max(t[i], ret); 75 | ret = max(vr[i] + mxl, ret); 76 | mxl = max(vl[i], mxl); 77 | } 78 | return ret; 79 | } 80 | 81 | 82 | int main() { 83 | ios::sync_with_stdio(false); 84 | cin.tie(0); 85 | cin >> n >> m >> A >> B; 86 | for(int i = 1, u, v, w; i < n; i++) { 87 | cin >> u >> v >> w; 88 | g[u].emplace_back(v, w); 89 | g[v].emplace_back(u, w); 90 | } 91 | dfs_scaffold(A, -1); 92 | for(int v: scaffold) { 93 | sub[v] = dfs_subtree(v, -1, v); 94 | } 95 | build(); 96 | for(int i = 0, C, D; i < m; i++) { 97 | cin >> C >> D; 98 | if(rev[C] > rev[D]) swap(C, D); 99 | cout << query(rev[C], rev[D]) << '\n'; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /GoogleCodeJam/CODEJAM08-R1A-A.rs: -------------------------------------------------------------------------------- 1 | #[allow(unused_imports)] 2 | use std::cmp::{max, min}; 3 | use std::io::{stdin, stdout, BufWriter, Write}; 4 | 5 | fn main() { 6 | let stdin_obj = stdin(); 7 | let mut scan = Scanner { 8 | stdin: stdin_obj.lock(), 9 | }; 10 | let out = &mut BufWriter::new(stdout()); 11 | 12 | let test_cases: usize = scan.read(); 13 | for t in 1..test_cases + 1 { 14 | let n: usize = scan.read(); 15 | let mut x: Vec = scan.read_vec(n); 16 | let mut y: Vec = scan.read_vec(n); 17 | x.sort_unstable(); 18 | y.sort_unstable_by(|a, b| b.cmp(a)); 19 | let mut ans: i64 = 0; 20 | for (x, y) in x.iter().zip(y.iter()) { 21 | ans += x * y; 22 | } 23 | writeln!(out, "Case #{}: {}", t, ans).ok(); 24 | } 25 | } 26 | 27 | #[derive(Default)] 28 | pub struct Scanner { 29 | stdin: R, 30 | } 31 | impl Scanner { 32 | pub fn read(&mut self) -> T { 33 | use std::io::Read; 34 | let buf = self 35 | .stdin 36 | .by_ref() 37 | .bytes() 38 | .map(|b| b.unwrap()) 39 | .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r') 40 | .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r') 41 | .collect::>(); 42 | unsafe { std::str::from_utf8_unchecked(&buf) } 43 | .parse() 44 | .ok() 45 | .expect("Parse error.") 46 | } 47 | pub fn read_line(&mut self) -> String { 48 | use std::io::Read; 49 | let buf = self 50 | .stdin 51 | .by_ref() 52 | .bytes() 53 | .map(|b| b.unwrap()) 54 | .skip_while(|&b| b == b'\n' || b == b'\r') 55 | .take_while(|&b| b != b'\n' && b != b'\r') 56 | .collect::>(); 57 | unsafe { std::str::from_utf8_unchecked(&buf) } 58 | .parse() 59 | .ok() 60 | .expect("Parse error.") 61 | } 62 | pub fn read_vec(&mut self, n: usize) -> Vec { 63 | (0..n).map(|_| self.read()).collect() 64 | } 65 | pub fn read_chars(&mut self) -> Vec { 66 | self.read::().chars().collect() 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /GoogleCodeJam/CODEJAM09-R1A-C.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 50; 4 | 5 | class Solver { 6 | 7 | long double mat[N][N], E[N], comb[N][N]; 8 | 9 | public: 10 | double solve() { 11 | int c, n; 12 | cin >> c >> n; 13 | comb[0][0] = 1; 14 | for(int i = 1; i <= c; i++) { 15 | comb[i][0] = comb[i][i] = 1; 16 | for(int j = 1; j < i; j++) comb[i][j] = comb[i-1][j-1] + comb[i-1][j]; 17 | } 18 | for(int x = 0; x < c; x++) { 19 | for(int y = x; y <= min(x + n, c); y++) { 20 | mat[x][y] = comb[c-x][y-x] / comb[c][n] * comb[x][n-(y-x)]; 21 | } 22 | } 23 | for(int i = c-1; i >= 0; i--) { 24 | E[i] = -1; 25 | for(int j = i+1; j <= c; j++) E[i] -= E[j] * mat[i][j]; 26 | E[i] /= (mat[i][i] - 1); 27 | } 28 | return E[0]; 29 | } 30 | }; 31 | 32 | int main() { 33 | ios::sync_with_stdio(false); 34 | cin.tie(0); 35 | int t; 36 | cin >> t; 37 | for(int i = 1; i <= t; i++) { 38 | Solver *solver = new Solver(); 39 | cout << "Case #" << i << ": " << solver->solve() << endl; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /GoogleCodeJam/CODEJAM19-QR-C.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | 4 | def find_begin_index(adj): 5 | for i in range(len(adj) - 1): 6 | if adj[i] != adj[i + 1]: 7 | return (i + 1, math.gcd(adj[i], adj[i + 1])) 8 | exit(1) 9 | 10 | 11 | def solve_case(): 12 | N, L = map(int, input().split()) 13 | adj = [int(x) for x in input().split()] 14 | cipher_text = [-1] * (L + 1) 15 | begin_index, cipher_text[begin_index] = find_begin_index(adj) 16 | for i in reversed(range(begin_index)): 17 | cipher_text[i] = adj[i] // cipher_text[i + 1] 18 | for i in range(begin_index, L): 19 | cipher_text[i + 1] = adj[i] // cipher_text[i] 20 | alphabet_primes = sorted(list(set(cipher_text))) 21 | alphabet = dict() 22 | assert(len(alphabet_primes) == 26) 23 | for i, prime in enumerate(alphabet_primes): 24 | alphabet[prime] = chr(ord('A') + i) 25 | message = ''.join([alphabet[x] for x in cipher_text]) 26 | return message 27 | 28 | 29 | def main(): 30 | n = int(input()) 31 | for i in range(n): 32 | print("Case #{}: {}".format(i + 1, solve_case())) 33 | 34 | 35 | if __name__ == "__main__": 36 | main() 37 | -------------------------------------------------------------------------------- /Hackerearth/temp.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galletas1712/CompetitiveProgramming/48f546f83bcab17211e9cea5a35edc1968344290/Hackerearth/temp.txt -------------------------------------------------------------------------------- /Hackerrank/HACKR house-location.cpp: -------------------------------------------------------------------------------- 1 | // Model the requirements as an equation, rearange it and complete the square to make a circle equation 2 | // Then you have to find the common point of the two circles that are minimum 3 | // https://stackoverflow.com/questions/3349125/circle-circle-intersection-points 4 | #include 5 | using namespace std; 6 | #define ld long double 7 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 8 | const int INF = 1e9+1; 9 | const ld EPS = 1e-13; 10 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 11 | 12 | class HouseLoc { 13 | 14 | ld a, b, x[5], y[5], r[2]; 15 | ld sq(ld x) { return x*x; } 16 | 17 | struct point { 18 | ld x, y; 19 | point operator+(point rhs) { 20 | return (point) {x + rhs.x, y + rhs.y}; 21 | } 22 | point operator-(point rhs) { 23 | return (point) {x - rhs.x, y - rhs.y}; 24 | } 25 | point operator*(ld a) { 26 | return (point) {x * a, y * a}; 27 | } 28 | point operator/(ld a) { 29 | return (point) {x / a, y / a}; 30 | } 31 | bool operator<(point rhs) { 32 | if(x < rhs.x - EPS) return true; 33 | if(abs(x - rhs.x) < EPS && y < rhs.y - EPS) return true; 34 | return false; 35 | } 36 | ld sqsz() { 37 | return x*x + y*y; 38 | } 39 | } P[5]; 40 | 41 | public: 42 | void solve(istream &cin, ostream &cout) { 43 | cout << fixed << setprecision(2); 44 | cin >> a >> b; 45 | a *= a; 46 | b *= b; 47 | for(int i = 0; i < 4; i++) cin >> x[i] >> y[i]; 48 | P[0] = {(a * x[1] - x[0]) / (a-1), (a * y[1] - y[0]) / (a-1)}; 49 | r[0] = sqrt((sq(x[0]) + sq(y[0]) - a * (sq(x[1]) + sq(y[1]))) / (a-1) + sq(P[0].x) + sq(P[0].y)); 50 | 51 | P[1] = {(b * x[3] - x[2]) / (b-1), (b * y[3] - y[2]) / (b-1)}; 52 | r[1] = sqrt((sq(x[2]) + sq(y[2]) - b * (sq(x[3]) + sq(y[3]))) / (b-1) + sq(P[1].x) + sq(P[1].y)); 53 | 54 | ld dist2 = (P[1] - P[0]).sqsz(); 55 | ld dist = sqrt(dist2); 56 | 57 | if(abs(P[0].x - P[1].x) < EPS && abs(P[0].y - P[1].y) < EPS && abs(r[0] - r[1]) < EPS) { 58 | cout << P[0].x - r[0] << ' ' << P[0].y << endl; 59 | return; 60 | } 61 | 62 | if(dist - EPS > r[0] + r[1] || dist < abs(r[0] - r[1]) - EPS) { 63 | cout << "Impossible!"; 64 | return; 65 | } 66 | 67 | ld A = (sq(r[0]) - sq(r[1]) + dist2) / (2.0 * dist); // distance from P0 (first center) to P2 (intersection of line connecting radii and midpoint of intersections) 68 | ld H = sqrt(sq(r[0]) - sq(A)); // distance from P2 to intersections 69 | P[2] = P[0] + (P[1] - P[0]) * A / dist; 70 | 71 | point orth = (P[1] - P[0]) * H / dist; // vector pointing from P2 to intersections 72 | swap(orth.x, orth.y); 73 | orth.x *= -1; 74 | P[3] = P[2] + orth; 75 | P[4] = P[2] - orth; 76 | if(P[3] < P[4]) cout << P[3].x << ' ' << P[3].y << endl; 77 | else cout << P[4].x << ' ' << P[4].y << endl; 78 | } 79 | }; 80 | 81 | class Solver { 82 | public: 83 | void solve(std::istream& in, std::ostream& out) { 84 | HouseLoc *obj = new HouseLoc(); 85 | obj->solve(in, out); 86 | delete obj; 87 | } 88 | }; 89 | 90 | int main() { 91 | ios::sync_with_stdio(false); 92 | cin.tie(0); 93 | Solver solver; 94 | std::istream& in(std::cin); 95 | std::ostream& out(std::cout); 96 | solver.solve(in, out); 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /Hackerrank/IOIPractice14-bouncebouncebounce.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | int n; 8 | cin >> n; 9 | int ans = 0; 10 | for(int i = 1; i <= n; i++) if(__gcd(i, n+1) == 1) ++ans; 11 | cout << ans; 12 | } 13 | -------------------------------------------------------------------------------- /Olympiad/APIO/APIO11-color.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Look at the image from http://momo-funnycodes.blogspot.com/2013/05/apio-2011-table-coloring.html 3 | We can see that if we fix the upper left hand corner, we can reduce the problem to boolean satisfiability with xors 4 | This can be done using a technique similar to when checking if a graph is bipartite 5 | */ 6 | #include 7 | #define long long long 8 | using namespace std; 9 | const int N = 2e5+1; 10 | 11 | int n, m, k, chk[N]; // chk contains prefix xor aggregate on path. Chechking done like finding odd cycles in graph 12 | bool can[2] = {1, 1}, mark[N]; 13 | vector > g[N]; 14 | 15 | bool dfs(int u, int x) { // x = a[1][1] 16 | mark[u] = true; 17 | bool ret = true; 18 | for(auto p: g[u]) { 19 | int v, w; 20 | tie(v, w) = p; 21 | if(mark[v]) { 22 | if(chk[u] ^ chk[v] != w ^ x) return false; // look at the table and you will see why we need an ^x at the end 23 | continue; 24 | } 25 | chk[v] = chk[u] ^ w ^ x; 26 | ret &= dfs(v, x); 27 | } 28 | return ret; 29 | } 30 | 31 | void add_edge(int u, int v, int w) { 32 | g[u].emplace_back(v, w); 33 | g[v].emplace_back(u, w); 34 | } 35 | 36 | long solve(int c) { 37 | fill(mark, mark+n+m+1, 0); 38 | fill(chk, chk+n+m+1, 0); 39 | int tot = 0; 40 | for(int i = 0; i <= n+m; i++) { 41 | if(i == 1 || i == n+1 || mark[i]) continue; 42 | if(!dfs(i, (!i && c))) { // only need c in component with root (i == 0 corresponds to a[1][1]) 43 | return 0; 44 | } 45 | tot += i != 0; 46 | } 47 | long ret = 1; 48 | while(tot--) ret *= 2, ret %= int(1e9); 49 | return ret; 50 | } 51 | 52 | void solve(istream& cin) { 53 | cin >> n >> m >> k; 54 | for(int i = 0, x, y, c; i < k; i++) { 55 | cin >> x >> y >> c; 56 | if(x == 1 && y == 1) can[c ^ 1] = false; 57 | else if(x == 1) { 58 | add_edge(0, y+n, c); 59 | } 60 | else if(y == 1) { 61 | add_edge(0, x, c); 62 | } 63 | else add_edge(x, y+n, c ^ (x % 2 == 0 && y % 2 == 0)); 64 | } 65 | long ans = 0; 66 | if(can[0]) ans += solve(0); 67 | if(can[1]) ans += solve(1); 68 | cout << ans % int(1e9) << endl; 69 | } 70 | 71 | int main() { 72 | ios::sync_with_stdio(false); 73 | cin.tie(0); 74 | solve(cin); 75 | } 76 | -------------------------------------------------------------------------------- /Olympiad/APIO/APIO17-merchant.cpp: -------------------------------------------------------------------------------- 1 | // binary search on efficiency 2 | // for every pair of vertices, we buy/sell the good with the maximum efficiency 3 | // when checking, create new adjacency matrix from rearranged inequality with fixed efficiency and check >= 0 4 | #include 5 | #define long long long 6 | using namespace std; 7 | const int N = 101; 8 | const long LINF = 1e16; 9 | 10 | int n, m, K, buy[N][1001], sell[N][1001]; 11 | long dist[N][N], dp[N][N], S[N][N]; 12 | 13 | bool check(long x) { 14 | for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) { 15 | dp[i][j] = -LINF; 16 | if(i != j && dist[i][j] != LINF && S[i][j] != -LINF) dp[i][j] = S[i][j] - x * dist[i][j]; 17 | } 18 | 19 | for(int k = 0; k < n; k++) { 20 | for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) if(i != k && j != k) { 21 | dp[i][j] = max(dp[i][k] + dp[k][j], dp[i][j]); 22 | } 23 | } 24 | 25 | for(int i = 0; i < n; i++) if(dp[i][i] >= 0) return true; 26 | return false; 27 | } 28 | 29 | int main() { 30 | ios::sync_with_stdio(false); 31 | cin.tie(0); 32 | cin >> n >> m >> K; 33 | for(int i = 0; i < n; i++) { 34 | for(int k = 0; k < K; k++) cin >> buy[i][k] >> sell[i][k]; 35 | } 36 | for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) if(i != j) dist[i][j] = LINF; 37 | for(int i = 0, u, v, w; i < m; i++) { 38 | cin >> u >> v >> w; 39 | --u, --v; 40 | dist[u][v] = min((long) w, dist[u][v]); 41 | } 42 | for(int k = 0; k < n; k++) { 43 | for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) if(i != j) { 44 | dist[i][j] = min(dist[i][k] + dist[k][j], dist[i][j]); 45 | } 46 | } 47 | for(int i = 0; i < n; i++) { 48 | for(int j = 0; j < n; j++) { 49 | S[i][j] = -LINF; 50 | if(dist[i][j] == LINF) continue; 51 | S[i][j] = 0; 52 | for(int k = 0; k < K; k++) if(sell[j][k] != -1 && buy[i][k] != -1) { 53 | S[i][j] = max((long) sell[j][k] - buy[i][k], S[i][j]); 54 | } 55 | } 56 | } 57 | long l = 0, r = 1e9; 58 | while(l < r) { 59 | long mid = l+r+1 >> 1; 60 | if(check(mid)) l = mid; 61 | else r = mid-1; 62 | } 63 | cout << l; 64 | } 65 | -------------------------------------------------------------------------------- /Olympiad/APIO/APIO18-duathlon.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Count complements 3 | * Consider some cut vertex u 4 | * We will only count invalid triples that cross u's BCCs 5 | * All three can't be in different BCCs, otherwise it's always valid 6 | * Therefore, two must be in one BCC and one must be in the other. 7 | * With this, there are two invalid orderings for each triple that satisfies the above constraints 8 | */ 9 | #include 10 | using namespace std; 11 | #define long long long 12 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 13 | const int INF = 1e9+1; 14 | const double EPS = 1e-10; 15 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 16 | const int N = 2e5+1; 17 | 18 | class Duathlon { 19 | 20 | int n, m; 21 | vector g[N]; 22 | long ans; 23 | 24 | int tick, ccs, tot, pre[N], low[N], d[N]; 25 | vector stk; 26 | vector bcg[N]; 27 | void dfs1(int u, int par) { 28 | pre[u] = low[u] = ++tick; 29 | stk.push_back(u); 30 | ++tot; 31 | for(int v: g[u]) { 32 | if(v == par) continue; 33 | if(!pre[v]) { 34 | dfs1(v, u); 35 | low[u] = min(low[v], low[u]); 36 | if(low[v] >= pre[u]) { 37 | ++ccs; 38 | bcg[u].push_back(n + ccs); 39 | vector curr; 40 | while(curr.empty() || curr.back() != v) { 41 | curr.push_back(stk.back()); 42 | stk.pop_back(); 43 | } 44 | bcg[n + ccs] = curr; 45 | } 46 | } else { 47 | low[u] = min(pre[v], low[u]); 48 | } 49 | } 50 | } 51 | 52 | long sz[N]; 53 | void dfs2(int u, int par) { 54 | sz[u] = u <= n; 55 | for(int v: bcg[u]) { 56 | dfs2(v, u); 57 | sz[u] += sz[v]; 58 | if(u > n) { 59 | ans -= 1ll * bcg[u].size() * sz[v] * (sz[v] - 1); 60 | } 61 | } 62 | if(u > n) { 63 | ans -= 1ll * bcg[u].size() * (tot - sz[u]) * (tot - sz[u] - 1); 64 | } 65 | } 66 | 67 | public: 68 | void solve(istream &cin, ostream &cout) { 69 | cin >> n >> m; 70 | for(int i = 0, u, v; i < m; i++) { 71 | cin >> u >> v; 72 | g[u].push_back(v); 73 | g[v].push_back(u); 74 | } 75 | for(int i = 1; i <= n; i++) { 76 | if(pre[i]) continue; 77 | dfs1(i, 0); 78 | dfs2(i, 0); 79 | ans += 1ll * tot * (tot - 1) * (tot - 2); 80 | tot = 0; 81 | } 82 | cout << ans << endl; 83 | } 84 | }; 85 | 86 | class Solver { 87 | public: 88 | void solve(std::istream& in, std::ostream& out) { 89 | Duathlon *obj = new Duathlon(); 90 | obj->solve(in, out); 91 | delete obj; 92 | } 93 | }; 94 | 95 | int main() { 96 | ios::sync_with_stdio(false); 97 | cin.tie(0); 98 | Solver solver; 99 | std::istream& in(std::cin); 100 | std::ostream& out(std::cout); 101 | solver.solve(in, out); 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /Olympiad/Balkan/Balkan11-timeismoney.cpp: -------------------------------------------------------------------------------- 1 | //http://www.boi2011.ro/resurse/tasks/timeismoney-sol.pdf 2 | #include 3 | using namespace std; 4 | #define all(a) begin(a), end(a) 5 | #define csz(a) (int) a.size() 6 | #define load(a, v) fill(begin(a), end(a), v) 7 | #define load_mem(a, v) memset(a, v, sizeof(a)); 8 | #define iostream_optimize() ios::sync_with_stdio(false); cin.tie(0); 9 | #define long long long 10 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 11 | const int INF = 1e9+1; 12 | const double EPS = 1e-10; 13 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 14 | 15 | struct edge { 16 | int u, v; 17 | long t, c; 18 | }; 19 | 20 | class TimeIsMoney { 21 | public: 22 | int n, m; 23 | vector edges; 24 | pair > res = {LINF, {LINF, LINF}}; 25 | istream* cin_ptr; 26 | ostream* cout_ptr; 27 | 28 | void tracer(long T, long C, vector trace_ls) { 29 | ostream& cout = *cout_ptr; 30 | cout << T << ' ' << C << '\n'; 31 | for(edge e: trace_ls) cout << e.u << ' ' << e.v << '\n'; 32 | } 33 | 34 | pair gen_mst(long a, long b, bool trace) { 35 | vector ls = edges, trace_ls; 36 | sort(ls.begin(), ls.end(), [a, b] (auto x, auto y) { return x.t * a + x.c * b < y.t * a + y.c * b; }); 37 | vector dsu(n, -1); 38 | function root; 39 | root = [&root, &dsu] (int v) { return (dsu[v] < 0 ? v : dsu[v] = root(dsu[v])); }; 40 | pair ret = {0, 0}; 41 | 42 | for(edge e: ls) { 43 | int u = root(e.u), v = root(e.v); 44 | if (u == v) continue; 45 | dsu[u] += dsu[v]; 46 | dsu[v] = u; 47 | ret.first += e.t; 48 | ret.second += e.c; 49 | if(trace) trace_ls.push_back(e); 50 | } 51 | 52 | res = min(make_pair(ret.first * ret.second, make_pair(a, b)), res); 53 | if(trace) tracer(ret.first, ret.second, trace_ls); 54 | 55 | return ret; 56 | } 57 | 58 | bool ccw(pair p1, pair p2, pair p3) { 59 | pair v1 = {p2.first - p1.first, p2.second - p1.second}; 60 | pair v2 = {p3.first - p2.first, p3.second - p2.second}; 61 | long cross = v1.first * v2.second - v1.second * v2.first; 62 | return cross > 0; 63 | } 64 | 65 | void rec(pair p1, pair p2) { 66 | res.first = min(p1.first * p1.second, res.first); 67 | res.first = min(p2.first * p2.second, res.first); 68 | long b = abs(p2.first - p1.first); 69 | long a = abs(p2.second - p1.second); 70 | auto opt = gen_mst(a, b, 0); 71 | if(ccw(p1, opt, p2)) rec(p1, opt), rec(opt, p2); 72 | } 73 | 74 | void solve(istream& in, ostream& out) { 75 | cin_ptr = ∈ 76 | cout_ptr = &out; 77 | istream& cin = *cin_ptr; 78 | ostream& cout = *cout_ptr; 79 | cin >> n >> m; 80 | for(int i = 0; i < m; i++) { 81 | edge e; 82 | cin >> e.u >> e.v >> e.t >> e.c; 83 | edges.push_back(e); 84 | } 85 | auto leftmost = gen_mst(1, 0, 0); 86 | auto bottommost = gen_mst(0, 1, 0); 87 | rec(leftmost, bottommost); 88 | gen_mst(res.second.first, res.second.second, 1); 89 | } 90 | }; 91 | 92 | int main() { 93 | ios::sync_with_stdio(false); 94 | cin.tie(0); 95 | TimeIsMoney solver; 96 | std::istream& in(std::cin); 97 | std::ostream& out(std::cout); 98 | solver.solve(in, out); 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /Olympiad/Balkan/Balkan18-election.cpp: -------------------------------------------------------------------------------- 1 | // Fix the right bound. This gives us exactly what to do for suffix sums. Then use segment tree to determine the lowest possible prefix sum value. 2 | // This simplifies the problem, as if we only consider one dimension (either prefix or suffix sums), the problem is much easier. This offline sorting does just that for us. 3 | 4 | #include 5 | using namespace std; 6 | #define long long long 7 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 8 | const int INF = 1e9+1; 9 | const double EPS = 1e-10; 10 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 11 | const int N = 1 << 19; 12 | 13 | class Elections { 14 | 15 | int n, q, ans[N]; 16 | string s; 17 | vector > qq[N]; 18 | 19 | int mn[2*N], lz[2*N]; 20 | void apply(int i, int l, int r) { 21 | if(!lz[i]) return; 22 | mn[i] += lz[i]; 23 | if(i < N) { 24 | lz[i << 1] += lz[i]; 25 | lz[i << 1 | 1] += lz[i]; 26 | } 27 | lz[i] = 0; 28 | } 29 | void update_mn(int tl, int tr, int v, int i = 1, int l = 0, int r = N-1) { 30 | apply(i, l, r); 31 | if(r < tl || l > tr) return; 32 | if(tl <= l && r <= tr) { 33 | lz[i] += v; 34 | apply(i, l, r); 35 | return; 36 | } 37 | int mid = l+r >> 1; 38 | update_mn(tl, tr, v, i << 1, l, mid); 39 | update_mn(tl, tr, v, i << 1 | 1, mid+1, r); 40 | mn[i] = min(mn[i << 1], mn[i << 1 | 1]); 41 | } 42 | int query_mn(int tl, int tr, int i = 1, int l = 0, int r = N-1) { 43 | apply(i, l, r); 44 | if(r < tl || l > tr) return INF; 45 | if(tl <= l && r <= tr) return mn[i]; 46 | int mid = l+r >> 1; 47 | return min(query_mn(tl, tr, i << 1, l, mid), query_mn(tl, tr, i << 1 | 1, mid+1, r)); 48 | } 49 | 50 | public: 51 | void run(istream &cin, ostream &cout) { 52 | cin >> n >> s >> q; 53 | for(int i = 0, l, r; i < q; i++) { 54 | cin >> l >> r; 55 | --l, --r; 56 | qq[r].emplace_back(l, i); 57 | } 58 | vector ts; 59 | for(int i = 0; i < n; i++) { 60 | if(s[i] == 'T') ts.push_back(i); 61 | else { 62 | if(!ts.empty()) { 63 | update_mn(ts.back(), n-1, -1); 64 | ts.pop_back(); 65 | } 66 | update_mn(i, n-1, 1); 67 | } 68 | for(auto p: qq[i]) { 69 | int j, qidx; 70 | tie(j, qidx) = p; 71 | int res = query_mn(j, i) - (j > 0 ? query_mn(j-1, j-1) : 0); 72 | auto it = lower_bound(ts.begin(), ts.end(), j); 73 | int cnt = (int) ts.size() - (it - ts.begin()); 74 | ans[qidx] = cnt - min(res, 0); 75 | } 76 | } 77 | for(int i = 0; i < q; i++) cout << ans[i] << '\n'; 78 | } 79 | }; 80 | 81 | class Solver { 82 | public: 83 | void solve(std::istream& in, std::ostream& out) { 84 | Elections *obj = new Elections(); 85 | obj->run(in, out); 86 | } 87 | }; 88 | 89 | int main() { 90 | ios::sync_with_stdio(false); 91 | cin.tie(0); 92 | Solver solver; 93 | std::istream& in(std::cin); 94 | std::ostream& out(std::cout); 95 | solver.solve(in, out); 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /Olympiad/Baltic/Baltic09-candy.cpp: -------------------------------------------------------------------------------- 1 | // Can go from i to j iff -x[i]+t[i] <= -x[j]+t[j] && x[i]+t[i] <= x[j]+t[j] 2 | // Partition into minimal number of LISes 3 | // Use greedy algorithm (chain with largest ending leq current value) 4 | // If the answer doesn't need to be recovered, use longest strictly decreasing subsequence (Dilworth's) 5 | #include 6 | using namespace std; 7 | const int N = 1e5+1, INF = 1e9+1; 8 | 9 | int n, x[N], t[N]; 10 | vector > a; 11 | set > st; 12 | vector > chains; 13 | int main() { 14 | ios::sync_with_stdio(false); 15 | cin.tie(0); 16 | cin >> n; 17 | for(int i = 0; i < n; i++) { 18 | cin >> x[i] >> t[i]; 19 | a.emplace_back(-x[i]+t[i], x[i]+t[i], i); 20 | } 21 | sort(a.begin(), a.end()); 22 | chains.push_back(vector()); 23 | st.emplace(-INF, 0); 24 | for(auto tt: a) { 25 | int p, q, i; 26 | tie(p, q, i) = tt; 27 | auto it = st.upper_bound(make_pair(q, INF)); 28 | if(it == st.begin()) { 29 | st.emplace(q, chains.size()); 30 | chains.push_back(vector()); 31 | chains.back().push_back(i); 32 | } else { 33 | it = prev(it); 34 | int idx = it->second; 35 | st.erase(it); 36 | chains[idx].push_back(i); 37 | st.emplace(q, idx); 38 | } 39 | } 40 | cout << chains.size() << '\n'; 41 | for(int i = 0; i < chains.size(); i++) { 42 | for(int j: chains[i]) cout << x[j] << ' ' << t[j] << ' ' << i+1 << '\n'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Olympiad/Baltic/Baltic17-PoliticalDevelopment.cpp: -------------------------------------------------------------------------------- 1 | // Use the property that every group has at least one node with degree < k 2 | // If we fix a node, we can find a clique (if exists) as all other members of the clique are adjacent to it by definition 3 | // So, we brute force using the adjacency list which takes O(2^deg) time 4 | // However, this is too slow, but notice that if we have tried setting a node to be in the clique already, we can eliminate it. 5 | // Since smaller degrees are more efficient, we eliminate the ones with smallest degree first. 6 | // Therefore, we sort the beginning nodes in order of degree. 7 | // Using the property previously stated, the time complexity always stays within O(2^k) for each beginning node. 8 | // Total time is O(n * 2^k) (haven't checked thoroughly) 9 | #include 10 | using namespace std; 11 | #define long long long 12 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 13 | const int INF = 1e9+1; 14 | const double EPS = 1e-10; 15 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 16 | const int N = 5e4+1; 17 | 18 | class NewPD { 19 | 20 | int n, k, ans; 21 | vector a[N], curr; 22 | bool vis[N]; 23 | 24 | void rec(int u, int i) { 25 | ans = max((int) curr.size(), ans); 26 | if(i == a[u].size() || ans == k) return; 27 | 28 | rec(u, i+1); 29 | 30 | if(vis[a[u][i]]) return; 31 | 32 | bool valid = true; 33 | for(int v: curr) { 34 | if(!binary_search(a[a[u][i]].begin(), a[a[u][i]].end(), v)) { 35 | valid = false; 36 | break; 37 | } 38 | } 39 | if(valid) { 40 | curr.push_back(a[u][i]); 41 | rec(u, i+1); 42 | curr.pop_back(); 43 | } 44 | } 45 | 46 | public: 47 | void solve(istream &cin, ostream &cout) { 48 | cin >> n >> k; 49 | for(int i = 0; i < n; i++) { 50 | int sz; 51 | cin >> sz; 52 | a[i].resize(sz); 53 | for(int j = 0; j < sz; j++) cin >> a[i][j]; 54 | sort(a[i].begin(), a[i].end()); 55 | } 56 | vector ord(n); 57 | iota(ord.begin(), ord.end(), 0); 58 | sort(ord.begin(), ord.end(), [&] (int x, int y) { return a[x].size() < a[y].size(); }); 59 | for(int i: ord) { 60 | vis[i] = true; 61 | curr.push_back(i); 62 | rec(i, 0); 63 | curr.pop_back(); 64 | } 65 | cout << ans; 66 | } 67 | }; 68 | 69 | class Solver { 70 | public: 71 | void solve(std::istream& in, std::ostream& out) { 72 | NewPD *obj = new NewPD(); 73 | obj->solve(in, out); 74 | delete obj; 75 | } 76 | }; 77 | 78 | int main() { 79 | ios::sync_with_stdio(false); 80 | cin.tie(0); 81 | Solver solver; 82 | std::istream& in(std::cin); 83 | std::ostream& out(std::cout); 84 | solver.solve(in, out); 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /Olympiad/Baltic/Baltic17-Railway.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5+1; 4 | 5 | int n, m, k; 6 | vector > g[N]; 7 | vector ls; 8 | 9 | int d[N]; 10 | vector anc[N]; 11 | void init_dfs(int u, int par) { 12 | for(auto p: g[u]) { 13 | int v, i; 14 | tie(v, i) = p; 15 | if(v == par) continue; 16 | 17 | d[v] = d[u] + 1; 18 | anc[v].push_back(u); 19 | for(int j = 0; 1 << j+1 <= d[v]; j++) 20 | anc[v].push_back(anc[anc[v][j]][j]); 21 | init_dfs(v, u); 22 | } 23 | } 24 | 25 | int get_lca(int u, int v) { 26 | if(d[u] < d[v]) swap(u, v); 27 | for(int j = 0; d[u] - d[v]; j++) 28 | if(d[u] - d[v] >> j & 1) u = anc[u][j]; 29 | if(u == v) return u; 30 | for(int j = 17; j >= 0; j--) 31 | if(j < anc[u].size() && anc[u][j] != anc[v][j]) 32 | u = anc[u][j], v = anc[v][j]; 33 | return anc[u][0]; 34 | } 35 | 36 | void add(int val, int num, map &f, int &cnt) { 37 | if(!f.count(val)) { 38 | assert(f[val] == 0); 39 | ++cnt; 40 | } 41 | f[val] += num; 42 | } 43 | 44 | void sub(int val, int num, map &f, int &cnt) { 45 | assert(f.count(val)); 46 | f[val] -= num; 47 | assert(f[val] >= 0); 48 | if(!f[val]) { 49 | --cnt; 50 | f.erase(val); 51 | } 52 | } 53 | 54 | vector > qq[N]; 55 | map f[N]; 56 | int cnt[N]; 57 | vector ans; 58 | void dfs(int u, int par) { 59 | for(auto p: g[u]) { 60 | int v, i; 61 | tie(v, i) = p; 62 | if(v == par) continue; 63 | dfs(v, u); 64 | if(cnt[v] >= k) ans.push_back(i); 65 | if(f[v].size() > f[u].size()) { 66 | swap(cnt[u], cnt[v]); 67 | swap(f[u], f[v]); 68 | } 69 | for(auto pp: f[v]) { 70 | add(pp.first, pp.second, f[u], cnt[u]); 71 | assert(pp.second > 0); 72 | } 73 | } 74 | for(auto p: qq[u]) { 75 | if(p.second >= 1) add(p.first, p.second, f[u], cnt[u]); 76 | else { 77 | sub(p.first, -p.second, f[u], cnt[u]); 78 | } 79 | } 80 | } 81 | 82 | int main() { 83 | ios::sync_with_stdio(false); 84 | cin.tie(0); 85 | cin >> n >> m >> k; 86 | for(int i = 1, u, v; i < n; i++) { 87 | cin >> u >> v; 88 | g[u].emplace_back(v, i); 89 | g[v].emplace_back(u, i); 90 | } 91 | init_dfs(1, -1); 92 | for(int i = 0; i < m; i++) { 93 | int sz; 94 | vector req; 95 | cin >> sz; 96 | req.resize(sz); 97 | for(int j = 0; j < sz; j++) { 98 | cin >> req[j]; 99 | qq[req[j]].emplace_back(i, 1); 100 | } 101 | int lca = req[0]; 102 | for(int j = 1; j < sz; j++) { 103 | lca = get_lca(req[j], lca); 104 | } 105 | qq[lca].emplace_back(i, -sz); 106 | } 107 | dfs(1, -1); 108 | sort(ans.begin(), ans.end()); 109 | cout << ans.size() << endl; 110 | for(int i: ans) cout << i << ' '; 111 | cout << endl; 112 | } 113 | -------------------------------------------------------------------------------- /Olympiad/Baltic/Baltic17-toll.cpp: -------------------------------------------------------------------------------- 1 | // Segment tree and model the problem somewhat like matrix multplication 2 | #include 3 | using namespace std; 4 | const int N = 5e4+1, INF = 1e9+1; 5 | 6 | int K, n, m, O; 7 | vector > I, adj[N], t[4*N]; 8 | 9 | vector > merge(vector > &a, vector > &b) { 10 | vector > res(K, vector(K, INF)); 11 | for(int x = 0; x < K; x++) for(int y = 0; y < K; y++) for(int z = 0; z < K; z++) { 12 | res[x][y] = min(a[x][z] + b[z][y], res[x][y]); 13 | } 14 | return res; 15 | } 16 | 17 | void build() { 18 | for(int i = 0; i < n; i++) t[n+i] = adj[i]; 19 | for(int i = n-1; i >= 1; i--) { 20 | t[i] = merge(t[i << 1], t[i << 1 | 1]); 21 | } 22 | } 23 | 24 | vector > query(int l, int r) { 25 | vector > resl = I, resr = I; 26 | for(l += n, r += n+1; l < r; l >>= 1, r >>= 1){ 27 | if(l & 1) resl = merge(resl, t[l++]); 28 | if(r & 1) resr = merge(t[--r], resr); 29 | } 30 | return merge(resl, resr); 31 | } 32 | int main() { 33 | ios::sync_with_stdio(false); 34 | cin.tie(0); 35 | cin >> K >> n >> m >> O; 36 | for(int i = 0; i < n; i++) adj[i] = vector >(K, vector(K, INF)); 37 | I = vector >(K, vector(K, INF)); 38 | for(int i = 0; i < K; i++) I[i][i] = 0; 39 | for(int i = 0, u, v, w; i < m; i++) { 40 | cin >> u >> v >> w; 41 | adj[u / K][u % K][v % K] = w; 42 | } 43 | build(); 44 | for(int i = 0, a, b; i < O; i++) { 45 | cin >> a >> b; 46 | vector > res = query(a / K, b / K - 1); 47 | if(a / K == b / K || res[a % K][b % K] == INF) cout << -1 << '\n'; 48 | else cout << res[a % K][b % K] << '\n'; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Olympiad/Baltic/BalticWarmup17-toast.cpp: -------------------------------------------------------------------------------- 1 | // Cosine rule to find radius. Impossible cases answer 0 D. 2 | #include 3 | using namespace std; 4 | #define long long long 5 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 6 | const int INF = 1e9+1; 7 | const double EPS = 1e-10; 8 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 9 | 10 | 11 | class Toast { 12 | int N, T; 13 | double D; 14 | public: 15 | void solve(istream& cin, ostream& cout) { 16 | cin >> N >> D >> T; 17 | if(T % N || (T / N) >= N/2) { 18 | cout << 0 << ' ' << D << endl; 19 | return; 20 | } 21 | T /= N; 22 | double R1 = sqrt(2) * D / sqrt(1 - cos(2*M_PI*(T+1)/N)); 23 | double R2 = sqrt(2) * D / sqrt(1 - cos(2*M_PI*T/N)); 24 | cout << fixed << R1 << ' ' << R2 << endl; 25 | } 26 | }; 27 | 28 | int main() { 29 | ios::sync_with_stdio(false); 30 | cin.tie(0); 31 | Toast solver; 32 | std::istream& in(std::cin); 33 | std::ostream& out(std::cout); 34 | solver.solve(in, out); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /Olympiad/CCO/CCO18-GradientDescent.cpp: -------------------------------------------------------------------------------- 1 | //https://github.com/SpeedOfMagic/CompetitiveProgramming/blob/master/CCO/18-GradientDescent.cpp 2 | #include 3 | using namespace std; 4 | 5 | int R, C, K; 6 | 7 | map, int> mp; 8 | int query(int x, int y) { 9 | if(mp.count(make_pair(x, y))) return mp[{x, y}]; 10 | cout << "? " << x << ' ' << y << endl; 11 | int res; 12 | cin >> res; 13 | mp[{x, y}] = res; 14 | return res; 15 | } 16 | 17 | int main() { 18 | cin >> R >> C >> K; 19 | int r_s = 1, r_e = R, c_s = 1, c_e = C; 20 | while(r_s < r_e-1 || c_s < c_e-1) { 21 | int r_mid = r_s + r_e >> 1, c_mid = c_s + c_e >> 1; 22 | int ret = query(r_mid, c_mid); 23 | if(r_s < r_e-1) { 24 | int r_ret = query(r_mid + 1, c_mid); 25 | if(ret < r_ret) r_e = r_mid; 26 | else r_s = r_mid; 27 | } 28 | if(c_s < c_e-1) { 29 | int c_ret = query(r_mid, c_mid + 1); 30 | if(ret < c_ret) c_e = c_mid; 31 | else c_s = c_mid; 32 | } 33 | } 34 | cout << "! " << min(min(query(r_s, c_s), query(r_s, c_e)), min(query(r_e, c_s), query(r_e, c_e))) << endl; 35 | } 36 | -------------------------------------------------------------------------------- /Olympiad/CEOI/CEOI13-treasure.cpp: -------------------------------------------------------------------------------- 1 | // Use idea of prefix sums. Try to calculate them while making the area dimensions of each query as large as possible. 2 | #include "treasure.h" 3 | #include 4 | using namespace std; 5 | 6 | int a[101][101]; 7 | map, int> mp; 8 | int query(int x1, int y1, int x2, int y2) { 9 | if(mp.count(make_tuple(x1, y1, x2, y2))) return mp[make_tuple(x1, y1, x2, y2)]; 10 | return mp[make_tuple(x1, y1, x2, y2)] = countTreasure(x1, y1, x2, y2); 11 | } 12 | void findTreasure (int N) { 13 | for(int i = 1; i <= N; i++) for(int j = 1; j <= N; j++) { 14 | if(i > N/2 && j > N/2) { 15 | a[i][j] = query(1, 1, i, j); 16 | } else if(i > N/2 && j <= N/2) { 17 | a[i][j] = query(1, 1, i, N) - query(1, j+1, i, N); 18 | } else if(i <= N/2 && j > N/2) { 19 | a[i][j] = query(1, 1, N, j) - query(i+1, 1, N, j); 20 | } else { 21 | a[i][j] = query(1, 1, N, N) - query(i+1, 1, N, N) - query(1, j+1, N, N) + query(i+1, j+1, N, N); 22 | } 23 | } 24 | for(int i = 1; i <= N; i++) for(int j = 1; j <= N; j++) if(a[i][j] - a[i-1][j] - a[i][j-1] + a[i-1][j-1]) Report(i, j); 25 | } 26 | -------------------------------------------------------------------------------- /Olympiad/CEOI/CEOI15-indcyc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1001; 4 | 5 | int n, m; 6 | vector > edges; 7 | vector g[N]; 8 | bool adj[N][N], used[N], blocked[N]; 9 | 10 | struct DSU { 11 | vector dsu; 12 | DSU(int n) { 13 | dsu = vector(n+1, -1); 14 | } 15 | void clear() { 16 | dsu.assign(n+1, -1); 17 | } 18 | int root(int v) { return (dsu[v] < 0 ? v : dsu[v] = root(dsu[v])); } 19 | void merge(int u, int v) { 20 | if((u = root(u)) == (v = root(v))) return; 21 | dsu[u] += dsu[v]; 22 | dsu[v] = u; 23 | } 24 | }; 25 | 26 | void dfs(int u, DSU &dsu) { 27 | used[u] = true; 28 | if(blocked[u]) return; 29 | for(int v: g[u]) if(!used[v]) { 30 | dfs(v, dsu); 31 | dsu.merge(u, v); 32 | } 33 | } 34 | 35 | void bfs(int x, int y, int rem) { 36 | vector dist(n+1, N), trace(n+1, -1); 37 | queue q; 38 | 39 | dist[x] = 0; 40 | q.push(x); 41 | 42 | while(!q.empty()) { 43 | int u = q.front(); 44 | q.pop(); 45 | for(int v: g[u]) if(v != rem && (!adj[rem][v] || v == y) && dist[u] + 1 < dist[v]) { 46 | trace[v] = u; 47 | dist[v] = dist[u] + 1; 48 | q.push(v); 49 | } 50 | } 51 | 52 | if(dist[y] == N) return; 53 | 54 | vector res; 55 | for(int v = y; v != -1; v = trace[v]) res.push_back(v); 56 | for(int v: res) cout << v << ' '; 57 | cout << rem << endl; 58 | exit(0); 59 | } 60 | 61 | int main() { 62 | cin >> n >> m; 63 | for(int i = 0, u, v; i < m; i++) { 64 | cin >> u >> v; 65 | edges.emplace_back(u, v); 66 | g[u].push_back(v); 67 | g[v].push_back(u); 68 | adj[u][v] = adj[v][u] = true; 69 | } 70 | 71 | for(int v = 1; v <= n; v++) { 72 | DSU dsu1 = DSU(n); 73 | for(int i = 1; i <= n; i++) used[i] = blocked[i] = false; 74 | used[v] = true; 75 | for(int x: g[v]) blocked[x] = true; 76 | 77 | vector ord; 78 | for(int i = 1; i <= n; i++) ord.push_back(i); 79 | stable_partition(ord.begin(), ord.end(), [] (int x) { return !blocked[x]; }); 80 | for(int i: ord) if(!used[i]) dfs(i, dsu1); 81 | 82 | for(int x: g[v]) for(int y: g[v]) if(x < y && !adj[x][y] && dsu1.root(x) == dsu1.root(y)) { 83 | bfs(x, y, v); 84 | } 85 | } 86 | cout << "no" << endl; 87 | } 88 | -------------------------------------------------------------------------------- /Olympiad/CEOI/CEOI15-teams.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * dp[j] = # of possible sequences with length i and maximum = j 3 | */ 4 | #include 5 | using namespace std; 6 | #define long long long 7 | const long MOD = 1e6+7, LINF = 1e18 + 1e16; 8 | const int INF = 1e9+1; 9 | const double EPS = 1e-10; 10 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 11 | const int N = 10001; 12 | 13 | class Calvinball { 14 | int n, a[N], mx[N]; 15 | long dp[N]; 16 | public: 17 | void solve(istream &cin, ostream &cout) { 18 | cin >> n; 19 | for(int i = 1; i <= n; i++) { 20 | cin >> a[i]; 21 | mx[i] = max(mx[i-1], a[i]); 22 | } 23 | for(int i = 1; i <= n; i++) { 24 | for(int j = i; j >= 1; j--) { 25 | dp[j] = (dp[j - 1] + 1ll * j * dp[j]) % MOD; 26 | } 27 | dp[mx[i-1]] += a[i] - 1; // need to mx[i-1] because we don't want to increase the maximum 28 | } 29 | long ans = 1; 30 | for(int i = 1; i <= n; i++) { 31 | ans = (ans + dp[i]) % MOD; 32 | } 33 | cout << ans << endl; 34 | } 35 | }; 36 | 37 | class Solver { 38 | public: 39 | void solve(std::istream& in, std::ostream& out) { 40 | Calvinball *obj = new Calvinball(); 41 | obj->solve(in, out); 42 | delete obj; 43 | } 44 | }; 45 | 46 | int main() { 47 | ios::sync_with_stdio(false); 48 | cin.tie(0); 49 | Solver solver; 50 | std::istream& in(std::cin); 51 | std::ostream& out(std::cout); 52 | solver.solve(in, out); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /Olympiad/COCI/COCI18-strah.cpp: -------------------------------------------------------------------------------- 1 | // Problem reduces to finding the sum of areas of every possible rectangle 2 | // Iterate lower right corner and use stack to separate different possible heights 3 | // Some rearranging of aggregate formula will give a separable equation 4 | #include 5 | #define long long long 6 | using namespace std; 7 | const int N = 2002; 8 | 9 | struct block { 10 | long h, l, r; 11 | block(long h, long l, long r): h(h), l(l), r(r) {} 12 | }; 13 | 14 | inline long get_agg1(block tmp) { 15 | return (tmp.r-tmp.l+1) * tmp.h * (tmp.h + 1) / 2; 16 | } 17 | 18 | inline long get_agg2(block tmp) { 19 | return (tmp.r * (tmp.r + 1) / 2 - tmp.l * (tmp.l - 1) / 2) * (tmp.h * (tmp.h + 1) / 2); // negative 20 | } 21 | 22 | int n, m, last[N], up[N][N]; 23 | char s[N][N]; 24 | long ans; 25 | 26 | long brute() { 27 | long actual = 0; 28 | for(int i = 0; i < n; i++) { 29 | for(int j = 0; j < m; j++) { 30 | if(s[i][j] == '#') continue; 31 | int mn = up[i][j]; 32 | long res = 0; 33 | for(int k = j; k >= 0; k--) { 34 | mn = min(up[i][k], mn); 35 | res += (mn * (mn + 1) / 2) * (j-k+1); // aggregate formula here 36 | } 37 | actual += res; 38 | // cerr << res << ' '; 39 | } 40 | // cerr << endl; 41 | } 42 | return actual; 43 | } 44 | 45 | int main() { 46 | ios::sync_with_stdio(false); 47 | cin.tie(0); 48 | cin >> n >> m; 49 | for(int i = 0; i < n; i++) cin >> s[i]; 50 | 51 | fill(last, last+N, -1); 52 | for(int i = 0; i < n; i++) { 53 | for(int j = 0; j < m; j++) { 54 | if(s[i][j] == '#') last[j] = i; 55 | else up[i][j] = i - last[j]; 56 | } 57 | } 58 | 59 | for(int i = 0; i < n; i++) { 60 | vector stk; 61 | long sum1 = 0, sum2 = 0; 62 | for(int j = 0, last = -1; j < m; j++) { 63 | if(!up[i][j]) { 64 | sum1 = 0; 65 | sum2 = 0; 66 | while(!stk.empty()) stk.pop_back(); 67 | last = j; 68 | continue; 69 | } 70 | while(!stk.empty() && stk.back().h >= up[i][j]) { 71 | block tmp = stk.back(); 72 | sum1 -= get_agg1(tmp); 73 | sum2 += get_agg2(tmp); 74 | stk.pop_back(); 75 | } 76 | block tmp = block(up[i][j], (stk.empty() ? last : stk.back().r + 1), j - 1); 77 | sum1 += get_agg1(tmp); 78 | sum2 -= get_agg2(tmp); 79 | stk.push_back(tmp); 80 | ans += sum1 * j + sum2; // sum2 is already negative 81 | } 82 | } 83 | cout << ans << endl; 84 | } 85 | -------------------------------------------------------------------------------- /Olympiad/COCI/COCI19-parametriziran.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define long long long 3 | using namespace std; 4 | 5 | int n, m; 6 | long ans; 7 | map ls[64][64]; 8 | void solve(istream& cin) { 9 | cin >> n >> m; 10 | for(int i = 0; i < n; i++) { 11 | string s; 12 | cin >> s; 13 | int h = 0, mask1 = 0; 14 | for(int j = 0; j < m; j++) if(s[j] != '?') mask1 |= 1 << j; 15 | int tmp[64]; 16 | fill(tmp, tmp+64, -1); 17 | for(int mask2 = 0; mask2 < 1 << m; mask2++) if((mask2 & mask1) == mask2) { 18 | int h = 0; 19 | for(int j = 0, p = 1; j < m; j++, p *= 26) { 20 | if(mask2 >> j & 1) { 21 | h += p * (s[j] - 'a'); 22 | } 23 | } 24 | tmp[mask2] = h; 25 | } 26 | // different mask2 27 | for(int mask2 = 0; mask2 < 1 << m; mask2++) { 28 | int and_mask = mask1 & mask2; 29 | int h = tmp[and_mask]; 30 | if(ls[mask2][and_mask].count(h)) 31 | ans += ls[mask2][and_mask][h]; 32 | } 33 | for(int mask2 = 0; mask2 < 1 << m; mask2++) if(tmp[mask2] >= 0) ++ls[mask1][mask2][tmp[mask2]]; 34 | } 35 | cout << ans; 36 | } 37 | 38 | int main() { 39 | ios::sync_with_stdio(false); 40 | cin.tie(0); 41 | solve(cin); 42 | } 43 | -------------------------------------------------------------------------------- /Olympiad/COCI/COCI19-slicice.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | 9 | class Slicice { 10 | 11 | int n, m, k; 12 | vector B, P; 13 | vector dp[2]; 14 | 15 | public: 16 | void solve(istream &cin, ostream &cout) { 17 | cin >> n >> m >> k; 18 | P = vector(n); 19 | B = vector(m + 1); 20 | for(int i = 0; i < n; i++) cin >> P[i]; 21 | for(int i = 0; i <= m; i++) cin >> B[i]; 22 | int pre = 0, now = 1; 23 | dp[0] = vector(k + 1, -INF); 24 | dp[1] = vector(k + 1, -INF); 25 | dp[0][0] = 0; 26 | for(int i = 0; i < n; i++, swap(pre, now)) { 27 | dp[now].assign(k + 1, -INF); 28 | for(int x = 0; x <= k; x++) { 29 | for(int y = 0; y <= x; y++) { 30 | if(P[i] + x - y > m) continue; 31 | int tmp = dp[pre][y] + B[P[i] + x - y]; 32 | dp[now][x] = max(tmp, dp[now][x]); 33 | } 34 | if(dp[now][x] < 0) dp[now][x] = -INF; 35 | } 36 | } 37 | cout << dp[pre][k] << endl; 38 | } 39 | }; 40 | 41 | class Solver { 42 | public: 43 | void solve(std::istream& in, std::ostream& out) { 44 | Slicice *obj = new Slicice(); 45 | obj->solve(in, out); 46 | delete obj; 47 | } 48 | }; 49 | 50 | int main() { 51 | ios::sync_with_stdio(false); 52 | cin.tie(0); 53 | Solver solver; 54 | std::istream& in(std::cin); 55 | std::ostream& out(std::cout); 56 | solver.solve(in, out); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /Olympiad/COI/COI06-patrik.cpp: -------------------------------------------------------------------------------- 1 | // sort in decreasing order of height and binary search for the left and right bounds. Update and count 2 | // intervals using fenwick tree 3 | #include 4 | using namespace std; 5 | const int N = 1 << 19; 6 | 7 | int n, f[N], f2[N]; 8 | vector > ls; 9 | long ans; 10 | 11 | void update(int i) { while(i < N) ++f[i], i += i & -i; } 12 | int query(int i) { 13 | int ret = 0; 14 | while(i > 0) ret += f[i], i -= i & -i; 15 | return ret; 16 | } 17 | int bsearch(int k) { 18 | int sum = 0, i = 0; 19 | for(int j = 18; j >= 0; j--) { 20 | if(sum + f[i + (1 << j)] <= k) { 21 | sum += f[i + (1 << j)]; 22 | i += 1 << j; 23 | } 24 | } 25 | return i; 26 | } 27 | void update2(int i) { while(i < N) ++f2[i], i += i & -i; } 28 | int query2(int i) { 29 | int ret = 0; 30 | while(i > 0) ret += f2[i], i -= i & -i; 31 | return ret; 32 | } 33 | 34 | int main() { 35 | ios::sync_with_stdio(false); 36 | cin.tie(0); 37 | cin >> n; 38 | ls.reserve(n); 39 | for(int i = 1, x; i <= n; i++) { 40 | cin >> x; 41 | ls.emplace_back(x, i); 42 | } 43 | sort(ls.begin(), ls.end(), greater>()); 44 | for(int i = 0, j = 0; i < n; i = j) { 45 | j = i; 46 | for(; j < n && ls[j].first == ls[i].first; j++) { 47 | int idx = ls[j].second; 48 | int lb, rb = min(bsearch(query(idx - 1)) + 1, n); 49 | int qidx = query(idx); 50 | int l = 1, r = idx; 51 | while(l < r) { 52 | int mid = l+r >> 1; 53 | if(qidx - query(mid - 1)) l = mid+1; 54 | else r = mid; 55 | } 56 | lb = max(l - 1, 1); 57 | ans += query2(rb) - query2(lb - 1); 58 | update2(idx); 59 | // cout << idx << ' ' << lb << ' ' << rb << ' ' << endl; 60 | } 61 | j = i; 62 | for(; j < n && ls[j].first == ls[i].first; j++) { 63 | update(ls[j].second); 64 | } 65 | } 66 | cout << ans; 67 | } 68 | -------------------------------------------------------------------------------- /Olympiad/IOI/IOI05-birthday.cpp: -------------------------------------------------------------------------------- 1 | // Reduces to finding intersection of ranges in circle 2 | // Need to optimize to pass. Used lack of cases to my advantage :) 3 | 4 | #include 5 | using namespace std; 6 | #define long long long 7 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 8 | const int INF = 1e9+1; 9 | const double EPS = 1e-10; 10 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 11 | const int N = 1e6+10; 12 | 13 | class Birthday { 14 | 15 | int n, a[N], cnt[N], lb[N], rb[N], tmp[2*N]; 16 | 17 | bool check(int d) { 18 | for(int i = 0; i < n; i++) { 19 | int current_rotation = (a[i] - i + n) % n; 20 | lb[i] = (current_rotation - d + n) % n; 21 | rb[i] = (current_rotation + d) % n; 22 | if(lb[i] <= rb[i]) { 23 | ++tmp[lb[i]]; 24 | --tmp[rb[i] + 1]; 25 | } else { 26 | ++tmp[lb[i]]; 27 | --tmp[rb[i] + n + 1]; 28 | } 29 | } 30 | int sum = 0; 31 | for(int i = 0; i < 2*n; i++) { 32 | sum += tmp[i]; 33 | cnt[i % n] += sum; 34 | } 35 | int mx = 0; 36 | for(int i = 0; i < n; i++) { 37 | mx = max(cnt[i], mx); 38 | } 39 | memset(tmp, 0, sizeof(tmp)); 40 | memset(cnt, 0, sizeof(cnt)); 41 | return mx == n; 42 | } 43 | 44 | public: 45 | void solve(istream &cin, ostream &cout) { 46 | cin >> n; 47 | for(int i = 0; i < n; i++) { 48 | cin >> a[i]; 49 | --a[i]; 50 | } 51 | int ans = n; 52 | int l = 0, r = n-1; 53 | while(l < r) { 54 | int mid = l+r >> 1; 55 | if(check(mid)) r = mid; 56 | else l = mid + 1; 57 | } 58 | ans = l; 59 | if(n < N/2) { 60 | reverse(a, a+n); 61 | int l = 0, r = n-1; 62 | while(l < r) { 63 | int mid = l+r >> 1; 64 | if(check(mid)) r = mid; 65 | else l = mid + 1; 66 | } 67 | ans = min(l, ans); 68 | } 69 | cout << ans << endl; 70 | } 71 | }; 72 | 73 | class Solver { 74 | public: 75 | void solve(std::istream& in, std::ostream& out) { 76 | Birthday *obj = new Birthday(); 77 | obj->solve(in, out); 78 | delete obj; 79 | } 80 | }; 81 | 82 | int main() { 83 | ios::sync_with_stdio(false); 84 | cin.tie(0); 85 | Solver solver; 86 | std::istream& in(std::cin); 87 | std::ostream& out(std::cout); 88 | solver.solve(in, out); 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /Olympiad/IOI/IOI18-doll.cpp: -------------------------------------------------------------------------------- 1 | // General idea is to use many trees (represented as bitmask). To access these trees, run through a filter. Provable that this whole system has <= n + log n nodes (canceling). 2 | #include "doll.h" 3 | #include 4 | using namespace std; 5 | const int N = 4e5+1; 6 | 7 | int m, n, need, nodes, c[N], l[N], r[N], x[N], y[N]; 8 | vector a; 9 | vector ls[N]; 10 | 11 | bool state[N], leaf_l[N], leaf_r[N]; 12 | 13 | void dfs(int i, int val) { 14 | bool org = state[i]; 15 | state[i] ^= 1; 16 | if(org) { 17 | if(r[i] == -1) { 18 | // cout << i << " r" << ' ' << val << endl; 19 | y[i] = val; 20 | } else dfs(r[i], val); 21 | } else { 22 | if(l[i] == -1) { 23 | // cout << i << " l" << ' ' << val << endl; 24 | x[i] = val; 25 | } else dfs(l[i], val); 26 | } 27 | } 28 | 29 | void create_circuit(int _m, vector _a) { 30 | m = _m, a = _a; 31 | n = a.size(); 32 | a.insert(a.begin(), 0); 33 | a.push_back(0); 34 | 35 | for(int i = 0; i < (int) a.size() - 1; i++) ls[a[i]].push_back(a[i+1]); 36 | 37 | for(int i = 0; i <= m; i++) { 38 | if(ls[i].empty()) c[i] = 1; 39 | else if(ls[i].size() == 1) c[i] = ls[i][0]; 40 | else c[i] = -1; 41 | } 42 | 43 | for(int i = 0; i < (int) a.size() - 1; i++) need += ls[a[i]].size() > 1; 44 | 45 | int lgn = log2(need); 46 | 47 | for(int i = 1; i <= lgn + 1; i++) { 48 | if(i <= lgn) l[i] = i+1, x[i] = -l[i]; 49 | else { 50 | l[i] = 1; 51 | r[i] = (need % 2 ? -1 : 1); 52 | leaf_l[i] = leaf_r[i] = 1; 53 | x[i] = y[i] = -1; 54 | } 55 | } 56 | nodes += log2(need) + 1; 57 | for(int i = 1; i <= lgn; i++) { 58 | int sz = 1 << (lgn + 1 - i); 59 | if(need & sz) { 60 | r[i] = nodes + 1; 61 | y[i] = -r[i]; 62 | for(int t = 1; t < sz; t++) { 63 | if(t < sz / 2) { 64 | l[nodes + t] = nodes + (t << 1); 65 | r[nodes + t] = nodes + (t << 1 | 1); 66 | x[nodes + t] = -l[nodes + t]; 67 | y[nodes + t] = -r[nodes + t]; 68 | } else { 69 | leaf_l[nodes + t] = leaf_r[nodes + t] = 1; 70 | l[nodes + t] = r[nodes + t] = -1; 71 | } 72 | } 73 | nodes += sz - 1; 74 | } else { 75 | r[i] = 1; 76 | y[i] = -1; 77 | leaf_r[i] = 1; 78 | } 79 | // cout << i << ' ' << nodes << ' ' << sz << ' ' << l[i] << ' ' << leaf_l[i] << ' ' << r[i] << ' ' << leaf_r[i] << endl; 80 | } 81 | // for(int i = 1; i <= nodes; i++) { 82 | // cout << i << ' ' << l[i] << ' ' << r[i] << ' ' << leaf_l[i] << ' ' << leaf_r[i] << endl; 83 | // } 84 | // 85 | for(int i = 0; i < (int) a.size() - 1; i++) { 86 | if(ls[a[i]].size() <= 1) continue; 87 | dfs(1, a[i+1]); 88 | } 89 | vector C, X, Y; 90 | for(int i = 0; i <= m; i++) C.push_back(c[i]); 91 | for(int i = 1; i <= nodes; i++) X.push_back(x[i]), Y.push_back(y[i]); 92 | 93 | // for(int i = 1; i <= nodes; i++) cout << -i << ' ' << x[i] << ' ' << y[i] << endl; 94 | 95 | answer(C, X, Y); 96 | } 97 | -------------------------------------------------------------------------------- /Olympiad/JOI/JOISC17-portfacility.cpp: -------------------------------------------------------------------------------- 1 | // Problem is to find the number of ways to color the edges such that those in the same set don't partially overlap (fully containing is fine) 2 | // Build a graph of segments that cannot be with each other. Equivalent to finding 2-coloring of this graph 3 | // If graph is not bipartite, we return 0 (check using undirected SCC = DSU) 4 | // Sort segments by left bound. If the answer is valid, then the segments that partially overlap this one should form a mountain shape. 5 | // We merge all of them is DSU and add an optimization to never merge them again. This gives O(n log n) amortized but with a pretty big constant. 6 | #include 7 | using namespace std; 8 | #define long long long 9 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 10 | const int INF = 1e9+1; 11 | const double EPS = 1e-10; 12 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 13 | const int N = 2e6+1; 14 | 15 | struct seg { 16 | int l, r, i; 17 | bool operator<(const seg &rhs) const { 18 | return r < rhs.r; 19 | } 20 | seg(int l, int r, int i): l(l), r(r), i(i) {} 21 | }; 22 | 23 | class PortFacility { 24 | 25 | int n, dsu[N]; 26 | vector a; 27 | set st; 28 | 29 | int root(int v) { 30 | return (dsu[v] < 0 ? v : dsu[v] = root(dsu[v])); 31 | } 32 | 33 | void merge(int u, int v) { 34 | if((u = root(u)) == (v = root(v))) return; 35 | dsu[u] += dsu[v]; 36 | dsu[v] = u; 37 | } 38 | 39 | public: 40 | void solve(istream &cin, ostream &cout) { 41 | cin >> n; 42 | for(int i = 0, l, r; i < n; i++) { 43 | cin >> l >> r; 44 | a.emplace_back(l, r, i); 45 | } 46 | sort(a.begin(), a.end(), [] (seg x, seg y) { return x.l < y.l; }); 47 | 48 | fill(dsu, dsu+2*n+1, -1); 49 | for(seg s: a) { 50 | while(!st.empty() && st.begin()->r < s.l) st.erase(st.begin()); 51 | auto lim = st.upper_bound(seg(-1, s.r, -1)); 52 | // cerr << "main" << s.l << ' ' << s.r << ' ' << s.i << endl; 53 | for(auto it = st.begin(); it != lim; ++it) { 54 | // cerr << it->l << ' ' << it->r << ' ' << it->i << endl; 55 | merge(s.i, it->i + n); 56 | merge(s.i + n, it->i); 57 | if(root(it->i) == root(prev(lim)->i)) break; 58 | } 59 | st.insert(s); 60 | } 61 | int cnt = 0; 62 | for(int i = 0; i < n; i++) { 63 | if(root(i) == root(i + n)) { 64 | cout << 0 << endl; 65 | return; 66 | } 67 | cnt += dsu[i] < 0; 68 | } 69 | long ans = 1; 70 | while(cnt--) ans = (ans <<= 1) % MOD; 71 | cout << ans << endl; 72 | } 73 | }; 74 | 75 | class Solver { 76 | public: 77 | void solve(std::istream& in, std::ostream& out) { 78 | PortFacility *obj = new PortFacility(); 79 | obj->solve(in, out); 80 | delete obj; 81 | } 82 | }; 83 | 84 | int main() { 85 | ios::sync_with_stdio(false); 86 | cin.tie(0); 87 | Solver solver; 88 | std::istream& in(std::cin); 89 | std::ostream& out(std::cout); 90 | solver.solve(in, out); 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /Olympiad/JOI/JOISC18-airline-Alice.cpp: -------------------------------------------------------------------------------- 1 | // https://ivaniscoding.wordpress.com/2018/08/27/communication-4-airline-route-map/ 2 | #include "Alicelib.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | const int K = 10; 9 | 10 | void Alice( int N, int M, int A[], int B[] ){ 11 | if(N == 1) { 12 | InitG(N, M); 13 | return; 14 | } 15 | if(N == 2) { 16 | InitG(N, M); 17 | if(M) MakeG(0, 0, 1); 18 | return; 19 | } 20 | std::vector > edges; 21 | for(int i = 0; i < M; i++) { 22 | edges.emplace_back(A[i], B[i]); // original graph 23 | } 24 | for(int i = 0; i < N; i++) { 25 | for(int j = 0; j < K; j++) { 26 | if(!((i + 1) >> j & 1)) continue; // make graph 1-indexed, so connect to corresponding nodes 27 | edges.emplace_back(i, N + j); // links between bit vertices and original vertices 28 | } 29 | } 30 | for(int j = 0; j < K - 1; j++) edges.emplace_back(N + j, N + j + 1); // links between bit vertices 31 | for(int i = 0; i < N; i++) { 32 | edges.emplace_back(i, N + K); // N + 10 is the special vertex 33 | } 34 | edges.emplace_back(N + K, N + K + 1); // N + 11 is the one-degree vertex 35 | int curr_idx = 0; 36 | InitG(N + K + 2, edges.size()); 37 | for(auto p: edges) MakeG(curr_idx++, p.first, p.second); 38 | } 39 | -------------------------------------------------------------------------------- /Olympiad/JOI/JOISC18-airline-Bob.cpp: -------------------------------------------------------------------------------- 1 | #include "Boblib.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | const int K = 10; 8 | 9 | void Bob(int N, int M, int A[], int B[]) { 10 | if(N == 1) { 11 | InitMap(N, M); 12 | return; 13 | } 14 | if(N == 2) { 15 | InitMap(N, M); 16 | for(int i = 0; i < M; i++) MakeMap(A[i], B[i]); 17 | return; 18 | } 19 | std::vector g[N]; 20 | for(int i = 0; i < M; i++) { 21 | g[A[i]].push_back(B[i]); 22 | g[B[i]].push_back(A[i]); 23 | } 24 | 25 | //find special vertex 26 | std::vector deg1; 27 | for(int i = 0; i < N; i++) if(g[i].size() == 1) deg1.push_back(i); 28 | assert(deg1.size() <= 2); // there can only be at most two vertices is degree one: max bit and very special vertex 29 | int very_special_vertex = deg1[0]; // vertex of degree 1 that points to the special vertex 30 | int special_vertex = g[deg1[0]][0]; 31 | if(deg1.size() == 2) { 32 | if(g[special_vertex].size() != N - K - 1) { 33 | very_special_vertex = deg1[1]; 34 | special_vertex = g[deg1[1]][0]; 35 | } 36 | } 37 | 38 | //find bit vertices 39 | std::vector bit_vertices; 40 | std::vector is_bit_vertex(N); 41 | for(int i = 0; i < N; i++) if(i != special_vertex) { 42 | if(std::find(g[i].begin(), g[i].end(), special_vertex) == g[i].end()) { 43 | bit_vertices.push_back(i); 44 | is_bit_vertex[i] = true; 45 | } 46 | } 47 | assert(bit_vertices.size() == K); 48 | 49 | // determine order of bit vertices and add 1 << ord to each of the original vertices at the same time 50 | int mx_bit_vertex = *min_element(bit_vertices.begin(), bit_vertices.end(), [&] (int i, int j) { return g[i].size() < g[j].size(); }); 51 | // observe that maximum bit vertex will be the one with the minimum degree 52 | std::vector vals(N); 53 | for(int ord = K - 1, curr = mx_bit_vertex; ord >= 0; ord--) { 54 | for(int v: g[curr]) { 55 | assert(v != very_special_vertex && v != special_vertex); 56 | if(is_bit_vertex[v]) continue; 57 | vals[v] |= 1 << ord; 58 | } 59 | 60 | for(int v: g[curr]) { 61 | if(is_bit_vertex[v]) { 62 | g[v].erase(std::find(g[v].begin(), g[v].end(), curr)); // total erase complexity is n^2 63 | curr = v; 64 | break; 65 | } 66 | } 67 | } 68 | 69 | auto in_org_graph = [&] (int v) -> bool { return v != very_special_vertex && v != special_vertex && !is_bit_vertex[v]; }; 70 | std::vector > ans; 71 | for(int i = 0; i < M; i++) { 72 | if(in_org_graph(A[i]) && in_org_graph(B[i])) ans.emplace_back(vals[A[i]] - 1, vals[B[i]] - 1); 73 | } 74 | InitMap(N - K - 2, ans.size()); 75 | for(auto p: ans) MakeMap(p.first, p.second); 76 | } 77 | -------------------------------------------------------------------------------- /Olympiad/POI/POI11-Rotation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | const int N = 4e5+1; 9 | 10 | class TreeRotations { 11 | 12 | int n, a[N], lc[N], rc[N], f[N]; 13 | long dp[N]; 14 | 15 | void update(int i, int v) { while(i <= n) f[i] += v, i += i & -i; } 16 | int query(int i) { 17 | int ret = 0; 18 | while(i > 0) ret += f[i], i -= i & -i; 19 | return ret; 20 | } 21 | 22 | int sz[N], st[N], en[N], rev[N]; 23 | void dfs1(int u) { 24 | if(!a[u]) { 25 | dfs1(lc[u]); 26 | dfs1(rc[u]); 27 | if(sz[rc[u]] > sz[lc[u]]) swap(lc[u], rc[u]); 28 | } 29 | sz[u] = sz[lc[u]] + sz[rc[u]] + 1; 30 | } 31 | 32 | void dfs2(int u) { 33 | static int tick = 0; 34 | st[u] = ++tick; 35 | rev[st[u]] = u; 36 | if(!a[u]) { 37 | dfs2(lc[u]); 38 | dfs2(rc[u]); 39 | } 40 | en[u] = tick; 41 | } 42 | 43 | void dfs3(int u, bool keep) { 44 | if(a[u]) { 45 | if(keep) update(a[u], 1); 46 | return; 47 | } 48 | dfs3(rc[u], 0); 49 | dfs3(lc[u], 1); 50 | long a0 = 0, a1 = 0; 51 | for(int i = st[rc[u]]; i <= en[rc[u]]; i++) if(a[rev[i]]) { 52 | a0 += query(a[rev[i]]); 53 | a1 += query(n) - query(a[rev[i]]); 54 | } 55 | dp[u] = dp[lc[u]] + dp[rc[u]] + min(a0, a1); 56 | for(int i = st[rc[u]]; i <= en[rc[u]]; i++) if(a[rev[i]]) update(a[rev[i]], 1); 57 | if(!keep) { 58 | for(int i = st[u]; i <= en[u]; i++) if(a[rev[i]]) update(a[rev[i]], -1); 59 | } 60 | } 61 | 62 | int node; 63 | int input(istream& cin) { 64 | int ret = ++node; 65 | cin >> a[ret]; 66 | if(a[ret] == 0) { 67 | lc[ret] = input(cin); 68 | rc[ret] = input(cin); 69 | } 70 | return ret; 71 | 72 | } 73 | 74 | public: 75 | void solve(istream &cin, ostream &cout) { 76 | cin >> n; 77 | input(cin); 78 | dfs1(1); 79 | dfs2(1); 80 | dfs3(1, 0); 81 | cout << dp[1] << endl; 82 | } 83 | }; 84 | 85 | class Solver { 86 | public: 87 | void solve(std::istream& in, std::ostream& out) { 88 | TreeRotations *obj = new TreeRotations(); 89 | obj->solve(in, out); 90 | delete obj; 91 | } 92 | }; 93 | 94 | int main() { 95 | ios::sync_with_stdio(false); 96 | cin.tie(0); 97 | Solver solver; 98 | std::istream& in(std::cin); 99 | std::ostream& out(std::cout); 100 | solver.solve(in, out); 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /Olympiad/POI/POI11-Rotation2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | const int N = 1e6+1; 9 | 10 | class TreeRotations { 11 | 12 | int n, a[2*N], lc[2*N], rc[2*N], f[N]; 13 | long dp[2*N]; 14 | 15 | void update(int i, int v) { while(i <= n) f[i] += v, i += i & -i; } 16 | int query(int i) { 17 | int ret = 0; 18 | while(i > 0) ret += f[i], i -= i & -i; 19 | return ret; 20 | } 21 | 22 | int st[2*N], en[2*N], rev[2*N]; 23 | int dfs1(int u) { 24 | if(!a[u]) { 25 | int szl = dfs1(lc[u]); 26 | int szr = dfs1(rc[u]); 27 | if(szr > szl) swap(lc[u], rc[u]); 28 | return szl + szr + 1; 29 | } else return 1; 30 | } 31 | 32 | int tick = 0; 33 | void dfs2(int u) { 34 | st[u] = ++tick; 35 | rev[st[u]] = u; 36 | if(!a[u]) { 37 | dfs2(lc[u]); 38 | dfs2(rc[u]); 39 | } 40 | en[u] = tick; 41 | } 42 | 43 | long a0, a1; 44 | void dfs3(int u, bool keep) { 45 | if(a[u]) { 46 | if(keep) update(a[u], 1); 47 | return; 48 | } 49 | dfs3(rc[u], 0); 50 | dfs3(lc[u], 1); 51 | a0 = 0, a1 = 0; 52 | for(int i = st[rc[u]]; i <= en[rc[u]]; i++) if(a[rev[i]]) { 53 | a0 += query(a[rev[i]]); 54 | a1 += query(n) - query(a[rev[i]]); 55 | } 56 | dp[u] = dp[lc[u]] + dp[rc[u]] + min(a0, a1); 57 | for(int i = st[rc[u]]; i <= en[rc[u]]; i++) if(a[rev[i]]) update(a[rev[i]], 1); 58 | if(!keep) { 59 | for(int i = st[u]; i <= en[u]; i++) if(a[rev[i]]) update(a[rev[i]], -1); 60 | } 61 | } 62 | 63 | int node; 64 | int input(istream& cin) { 65 | int ret = ++node; 66 | cin >> a[ret]; 67 | if(a[ret] == 0) { 68 | lc[ret] = input(cin); 69 | rc[ret] = input(cin); 70 | } 71 | return ret; 72 | } 73 | 74 | public: 75 | void solve(istream &cin, ostream &cout) { 76 | cin >> n; 77 | input(cin); 78 | dfs1(1); 79 | dfs2(1); 80 | dfs3(1, 0); 81 | cout << dp[1] << endl; 82 | } 83 | }; 84 | 85 | class Solver { 86 | public: 87 | void solve(std::istream& in, std::ostream& out) { 88 | TreeRotations *obj = new TreeRotations(); 89 | obj->solve(in, out); 90 | delete obj; 91 | } 92 | }; 93 | 94 | int main() { 95 | ios::sync_with_stdio(false); 96 | cin.tie(0); 97 | Solver solver; 98 | std::istream& in(std::cin); 99 | std::ostream& out(std::cout); 100 | solver.solve(in, out); 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /Olympiad/POI/POI14-panels.cpp: -------------------------------------------------------------------------------- 1 | // Do case analysis with sqrt. Look at both the panel size if it is less than sqrt, but quotients if it is more than sqrt, as the number of quotients is always <= sqrt 2 | // We can use the quotient of one dimension to check with the other dimension as we only use right bounds. 3 | #include 4 | using namespace std; 5 | 6 | int n; 7 | int main() { 8 | ios::sync_with_stdio(false); 9 | cin.tie(0); 10 | cin >> n; 11 | while(n--) { 12 | int a1, a2, b1, b2; 13 | cin >> a1 >> a2 >> b1 >> b2; 14 | auto can = [&] (int x) -> bool { 15 | return (a1+x-1) / x <= a2 / x && (b1+x-1) / x <= b2 / x; 16 | }; 17 | int ans = 1, lim = max(sqrt(a2), sqrt(b2)) + 1; 18 | for(int x = 1; x <= lim; x++) { 19 | if(can(x)) ans = max(x, ans); 20 | if((a1+x-1) / x <= a2 / x && can(a2 / x)) ans = max(a2 / x, ans); 21 | if((b1+x-1) / x <= b2 / x && can(b2 / x)) ans = max(b2 / x, ans); 22 | } 23 | cout << ans << '\n'; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Olympiad/TOKI/TOKIOpen18-CellsTour.cpp: -------------------------------------------------------------------------------- 1 | // Construct bipartite graph of x -> y 2 | // The row swap and column swap operations only switch the labels on the nodes 3 | // Graph remains isomorphic 4 | // We want to have to maximum number of points on the diagonal, which means we will select a matching from the bipartite graph 5 | // For each pair, we can make their labels equal in order to put it on the main diagonal (but not needed in implementation, just the idea) 6 | // So, the problem reduces to finding a maximum matching on this bipartite graph 7 | // Can be done in O(VE) = O(N^3) using a recursive greedy algorithm 8 | #include "tour.h" 9 | #include 10 | using namespace std; 11 | const int INF = 1e9+1; 12 | const int N = 301; 13 | 14 | int n; 15 | vector s; 16 | vector > g; 17 | vector mp; 18 | vector block; 19 | bool can_match(int u) { 20 | for(int v: g[u]) if(!block[v]) { 21 | block[v] = true; 22 | if(mp[v] == -1 || can_match(mp[v])) { 23 | mp[v] = u; 24 | return true; 25 | } 26 | } 27 | return false; 28 | } 29 | 30 | int getShortestTour(int _n, vector _s) { 31 | n = _n, s = _s; 32 | g = vector >(2*n); 33 | mp = vector(2*n, -1); 34 | block = vector(2*n, 0); 35 | for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) if(s[i][j] == '.') { 36 | g[i].push_back(j + n); 37 | g[j + n].push_back(i); 38 | } 39 | int sz = 0; 40 | for(int i = 0; i < n; i++) { 41 | block.assign(2*n, 0); 42 | if(can_match(i)) ++sz; 43 | } 44 | sz = min(n-1, sz); 45 | return 2*(n-1) - sz; 46 | } 47 | -------------------------------------------------------------------------------- /Olympiad/USACO/USACO16mar-262144-plat.cpp: -------------------------------------------------------------------------------- 1 | // It can be proven that we can always merge from right to left. 2 | // dp[i][k] = rightmost index we need to keep merging from the right to such that we get value k after merge 3 | #include 4 | using namespace std; 5 | #define long long long 6 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 7 | const int INF = 1e9+1; 8 | const double EPS = 1e-10; 9 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 10 | const int N = 262144 + 10; 11 | 12 | class Problem1 { 13 | 14 | int n, ans, a[N], dp[N][100]; 15 | 16 | public: 17 | void solve(istream &cin, ostream &cout) { 18 | cin >> n; 19 | for(int i = 1; i <= n; i++) cin >> a[i]; 20 | memset(dp, -1, sizeof(dp)); 21 | for(int i = 1; i <= n; i++) { 22 | dp[i][a[i]] = i-1; 23 | for(int k = a[i]+1; k < 100; k++) { 24 | if(dp[i][k-1] >= 0) { 25 | dp[i][k] = dp[dp[i][k-1]][k-1]; 26 | } 27 | if(dp[i][k] != -1) { 28 | ans = max(k, ans); 29 | } 30 | // cerr << i << ' ' << k << ' ' << dp[i][k] << endl; 31 | } 32 | } 33 | cout << ans << endl; 34 | } 35 | }; 36 | 37 | class Solver { 38 | public: 39 | void solve(std::istream& in, std::ostream& out) { 40 | Problem1 *obj = new Problem1(); 41 | obj->solve(in, out); 42 | delete obj; 43 | } 44 | }; 45 | 46 | int main() { 47 | ios::sync_with_stdio(false); 48 | cin.tie(0); 49 | Solver solver; 50 | std::ifstream in("262144.in"); 51 | std::ofstream out("262144.out"); 52 | solver.solve(in, out); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /Olympiad/USACO/USACO17feb-friendcross-plat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | 9 | class WhyDidTheCowCrossTheRoad3 { 10 | int n, K; 11 | long ans; 12 | vector a, b, revb; 13 | vector > ls, t; 14 | vector > ord; 15 | void allocate() { 16 | ans = 0; 17 | a = vector(n+1); 18 | b = vector(n+1); 19 | revb = vector(n+1); 20 | ls = vector >(2*(n+1)); 21 | t = vector >(2*(n+1)); 22 | } 23 | void build() { 24 | for(int i = 0; i < n; i++) ls[n+i].push_back(b[i]); 25 | for(int i = n-1; i >= 1; i--) { 26 | ls[i].resize(ls[i << 1].size() + ls[i << 1 | 1].size()); 27 | merge(ls[i << 1].begin(), ls[i << 1].end(), ls[i << 1 | 1].begin(), ls[i << 1 | 1].end(), ls[i].begin()); 28 | ls[i].resize(unique(ls[i].begin(), ls[i].end()) - ls[i].begin()); 29 | } 30 | for(int i = 0; i < 2*(n+1); i++) t[i].resize(ls[i].size() + 1); 31 | } 32 | int get_rb(vector &arr, int v) { 33 | auto it = upper_bound(arr.begin(), arr.end(), v); 34 | if(arr.empty() || it == arr.begin()) return -1; 35 | return it - arr.begin() - 1; 36 | } 37 | int get_lb(vector &arr, int v) { 38 | auto it = lower_bound(arr.begin(), arr.end(), v); 39 | if(arr.empty() || it == arr.end()) return -1; 40 | return it - arr.begin(); 41 | } 42 | void fen_update(vector &f, int i) { 43 | ++i; 44 | assert(0 <= i && i < f.size()); 45 | while(i < f.size()) ++f[i], i += i & -i; 46 | } 47 | int fen_query(vector &f, int i) { 48 | ++i; 49 | assert(0 <= i && i < f.size()); 50 | int ret = 0; 51 | while(i > 0) ret += f[i], i -= i & -i; 52 | return ret; 53 | } 54 | void update(int i, int v) { 55 | i += n; 56 | fen_update(t[i], get_lb(ls[i], v)); 57 | while(i >>= 1) fen_update(t[i], get_lb(ls[i], v)); 58 | } 59 | int query(int l, int r, int lv, int rv) { 60 | int ret = 0; 61 | for(l += n, r += n+1; l < r; l >>= 1, r >>= 1) { 62 | if(l & 1) { 63 | int lb = get_lb(ls[l], lv), rb = get_rb(ls[l], rv); 64 | if(lb != -1 && rb != -1) ret += fen_query(t[l], rb) - fen_query(t[l], lb-1); 65 | l++; 66 | } 67 | if(r & 1) { 68 | --r; 69 | int lb = get_lb(ls[r], lv), rb = get_rb(ls[r], rv); 70 | if(lb != -1 && rb != -1) ret += fen_query(t[r], rb) - fen_query(t[r], lb-1); 71 | } 72 | } 73 | return ret; 74 | } 75 | public: 76 | void solve() { 77 | freopen("friendcross.in", "r", stdin); 78 | freopen("friendcross.out", "w", stdout); 79 | cin >> n >> K; 80 | allocate(); 81 | for(int i = 0; i < n; i++) { 82 | cin >> a[i]; 83 | --a[i]; 84 | } 85 | for(int i = 0; i < n; i++) { 86 | cin >> b[i]; 87 | --b[i]; 88 | revb[b[i]] = i; 89 | } 90 | build(); 91 | for(int i = 0; i < n; i++) { 92 | ans += query(revb[a[i]] + 1, n-1, 0, n-1) - query(revb[a[i]] + 1, n-1, max(a[i]-K, 0), min(a[i]+K, n-1)); 93 | update(revb[a[i]], a[i]); // do get_lb in update function 94 | } 95 | cout << ans; 96 | } 97 | }; 98 | 99 | int main() { 100 | cin.tie(0); 101 | WhyDidTheCowCrossTheRoad3 solver; 102 | solver.solve(); 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /Olympiad/USACO/USACO18dec-gathering-plat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | const int N = 1e5+1; 9 | 10 | class gathering { 11 | 12 | int n, m; 13 | vector g[N], ls[N], rev_ls[N]; 14 | bool res[N]; 15 | 16 | int mark[N]; 17 | bool has_cycle = false; 18 | void find_cycle(int u) { 19 | mark[u] = 1; 20 | for(int v: ls[u]) { 21 | if(!mark[v]) { 22 | find_cycle(v); 23 | } else if(mark[v] == 1) { 24 | has_cycle = true; 25 | } 26 | } 27 | mark[u] = 2; 28 | } 29 | 30 | int d[N], st[N], en[N], up_edges; 31 | vector anc[N]; 32 | 33 | int get_lca(int u, int v) { 34 | if(d[u] < d[v]) swap(u, v); 35 | for(int j = 17; j >= 0; j--) if(d[u] - d[v] >> j & 1) u = anc[u][j]; 36 | if(u == v) return u; 37 | for(int j = 17; j >= 0; j--) if(j < anc[u].size() && anc[u][j] != anc[v][j]) 38 | u = anc[u][j], v = anc[v][j]; 39 | return anc[u][0]; 40 | } 41 | 42 | void init_dfs(int u, int p) { 43 | static int tick = 0; 44 | st[u] = ++tick; 45 | for(int v: g[u]) if(v != p) { 46 | d[v] = d[u] + 1; 47 | anc[v].push_back(u); 48 | for(int j = 0; 1 << j+1 <= d[v]; j++) 49 | anc[v].push_back(anc[anc[v][j]][j]); 50 | init_dfs(v, u); 51 | } 52 | en[u] = tick; 53 | } 54 | 55 | void count_ups(int u, int p) { 56 | for(int v: g[u]) if(v != p) { 57 | count_ups(v, u); 58 | } 59 | for(int v: ls[u]) { 60 | int lca = get_lca(u, v); 61 | up_edges += lca == v; 62 | } 63 | } 64 | 65 | void dfs2(int u, int p) { 66 | if(!up_edges) res[u] = 1; 67 | // assert(up_edges >= 0); 68 | for(int v: g[u]) if(v != p) { 69 | int org = up_edges; 70 | for(int w: rev_ls[u]) { 71 | up_edges -= st[v] <= st[w] && st[w] <= en[v]; 72 | } 73 | for(int w: rev_ls[v]) { 74 | up_edges += !(st[v] <= st[w] && st[w] <= en[v]); 75 | } 76 | dfs2(v, u); 77 | up_edges = org; 78 | } 79 | } 80 | 81 | public: 82 | void solve(istream &cin, ostream &cout) { 83 | cin >> n >> m; 84 | for(int i = 1, u, v; i < n; i++) { 85 | cin >> u >> v; 86 | --u, --v; 87 | g[u].push_back(v); 88 | g[v].push_back(u); 89 | } 90 | for(int i = 0, u, v; i < m; i++) { 91 | cin >> u >> v; 92 | --u, --v; 93 | ls[v].push_back(u); 94 | rev_ls[u].push_back(v); 95 | } 96 | find_cycle(0); 97 | if(has_cycle) { 98 | for(int i = 0; i < n; i++) cout << 0 << '\n'; 99 | return; 100 | } 101 | init_dfs(0, -1); 102 | count_ups(0, -1); 103 | dfs2(0, -1); 104 | for(int i = 0; i < n; i++) cout << res[i] << '\n'; 105 | } 106 | }; 107 | 108 | 109 | class Solver { 110 | public: 111 | void solve(std::istream& in, std::ostream& out) { 112 | gathering *obj = new gathering(); 113 | obj->solve(in, out); 114 | delete obj; 115 | } 116 | }; 117 | 118 | int main() { 119 | ios::sync_with_stdio(false); 120 | cin.tie(0); 121 | Solver solver; 122 | std::ifstream in("gathering.in"); 123 | std::ofstream out("gathering.out"); 124 | solver.solve(in, out); 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /Olympiad/USACO/USACO18mar-disrupt-plat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 5e4+1; 4 | 5 | int n, m, res[N]; 6 | vector g[N]; 7 | vector > edges; 8 | vector > queries; 9 | 10 | int t[2*N]; 11 | void update(int i, int v) { 12 | i += N; 13 | for(t[i] = min(v, t[i]); i > 1; i >>= 1) t[i>>1] = min(t[i], t[i^1]); 14 | } 15 | int query(int l, int r) { 16 | int res = INT_MAX; 17 | for(l += N, r += N+1; l < r; l >>= 1, r >>= 1) { 18 | if(l & 1) res = min(t[l++], res); 19 | if(r & 1) res = min(t[--r], res); 20 | } 21 | return res; 22 | } 23 | 24 | int curr_time, par[N], in[N], out[N]; 25 | void dfs(int u) { 26 | in[u] = ++curr_time; 27 | for(int v: g[u]) if(v != par[u]) { 28 | par[v] = u; 29 | dfs(v); 30 | } 31 | out[u] = curr_time; 32 | } 33 | 34 | int main() { 35 | freopen("disrupt.in", "r", stdin); 36 | freopen("disrupt.out", "w", stdout); 37 | // ios::sync_with_stdio(false); 38 | cin.tie(0); 39 | cin >> n >> m; 40 | for(int i = 0, u, v; i < n-1; i++) { 41 | cin >> u >> v; --u; --v; 42 | g[u].push_back(v); 43 | g[v].push_back(u); 44 | edges.emplace_back(u, v); 45 | } 46 | par[0] = -1; 47 | dfs(0); 48 | for(int i = 0, u, v, w; i < m; i++) { 49 | cin >> u >> v >> w; --u; --v; 50 | if(in[u] > in[v]) swap(u, v); 51 | queries.emplace_back(in[u], 1, in[v], w); // only want less l 52 | } 53 | for(int i = 0; i < n; i++) queries.emplace_back(in[i], 0, out[i], i); 54 | 55 | sort(queries.begin(), queries.end()); 56 | fill(res, res+n, INT_MAX); 57 | fill(t, t+2*N, INT_MAX); 58 | 59 | for(auto qq: queries) { 60 | int l, tp, r, wi; 61 | tie(l, tp, r, wi) = qq; 62 | if(tp) update(r, wi); 63 | else res[wi] = min(query(l, r), res[wi]); 64 | } 65 | 66 | for(auto& qq: queries) { 67 | swap(get<0>(qq), get<2>(qq)); 68 | get<1>(qq) ^= 1; 69 | } 70 | sort(queries.begin(), queries.end(), greater>()); 71 | fill(t, t+2*N, INT_MAX); 72 | 73 | for(auto qq: queries) { 74 | int r, tp, l, wi; 75 | tie(r, tp, l, wi) = qq; 76 | if(!tp) update(l, wi); 77 | else res[wi] = min(query(l, r), res[wi]); 78 | } 79 | 80 | for(auto e: edges) { 81 | int u, v; tie(u, v) = e; 82 | if(in[u] > in[v]) swap(u, v); 83 | cout << (res[v] == INT_MAX ? -1 : res[v]) << '\n'; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Olympiad/USACO/USACO18mar-sort-gold.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | 9 | class OutOfSorts { 10 | public: 11 | void solve(istream &cin, ostream &cout) { 12 | int n; 13 | vector a, b; 14 | multiset sta, stb; 15 | cin >> n; 16 | a.resize(n); 17 | for(int i = 0; i < n; i++) { 18 | cin >> a[i]; 19 | b.push_back(a[i]); 20 | } 21 | sort(b.begin(), b.end()); 22 | int ans = 1; 23 | for(int i = 0; i < n; i++) { 24 | if(stb.count(a[i])) { 25 | stb.erase(stb.find(a[i])); 26 | } else { 27 | sta.insert(a[i]); 28 | } 29 | if(sta.count(b[i])) { 30 | sta.erase(sta.find(b[i])); 31 | } else { 32 | stb.insert(b[i]); 33 | } 34 | assert(sta.size() == stb.size()); 35 | ans = max((int) sta.size(), ans); 36 | } 37 | cout << ans; 38 | } 39 | }; 40 | 41 | class Solver { 42 | public: 43 | void solve(std::istream& in, std::ostream& out) { 44 | OutOfSorts *obj = new OutOfSorts(); 45 | obj->solve(in, out); 46 | delete obj; 47 | } 48 | }; 49 | 50 | int main() { 51 | ios::sync_with_stdio(false); 52 | cin.tie(0); 53 | Solver solver; 54 | std::ifstream in("sort.in"); 55 | std::ofstream out("sort.out"); 56 | solver.solve(in, out); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /Olympiad/USACO/USACO18mar-sort-plat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5+1; 4 | 5 | int n, a[N], part[N]; 6 | pair b[N]; 7 | long long ans; 8 | int main() { 9 | freopen("sort.in", "r", stdin); 10 | freopen("sort.out", "w", stdout); 11 | cin.tie(0); 12 | cin >> n; 13 | for(int i = 1; i <= n; i++) { 14 | cin >> a[i]; 15 | b[i] = {a[i], i}; 16 | } 17 | sort(b+1, b+n+1); 18 | part[0] = part[n] = 0; 19 | for(int i = 1, mx = 0; i < n; i++) { 20 | mx = max(b[i].second, mx); 21 | part[i] = max(mx - i, 1); // max 1 in case it is already partitioned before bubble 22 | } 23 | for(int i = 1; i <= n; i++) ans += max(part[i-1], part[i]); 24 | cout << ans; 25 | } 26 | -------------------------------------------------------------------------------- /Olympiad/USACO/USACO19jan-redistricting-plat.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * code generated by JHelper 3 | * More info: https://github.com/AlexeyDmitriev/JHelper 4 | * @author 5 | */ 6 | 7 | /* 8 | * Use prefix sum of +1, -1 9 | * dp[i] = min(dp[j] + (S[i] < S[j])) 10 | * So partition j into cases where S[i] < S[j] and S[i] >= S[j] using segment tree 11 | */ 12 | #include 13 | using namespace std; 14 | #define long long long 15 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 16 | const int INF = 1e9+1; 17 | const double EPS = 1e-10; 18 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 19 | const int N = 3e5+10, M = 2*N; 20 | 21 | class redistricting { 22 | 23 | int n, k, S[N], dp[N]; 24 | string s; 25 | multiset ls[M]; 26 | int t[2*M]; 27 | 28 | void ins(int i, int v) { 29 | ls[i].insert(v); 30 | t[i + M] = *ls[i].begin(); 31 | for(i += M; i > 1; i >>= 1) 32 | t[i >> 1] = min(t[i], t[i ^ 1]); 33 | } 34 | 35 | void del(int i, int v) { 36 | ls[i].erase(ls[i].find(v)); 37 | t[i + M] = (ls[i].empty() ? INF : *ls[i].begin()); 38 | for(i += M; i > 1; i >>= 1) { 39 | t[i >> 1] = min(t[i], t[i ^ 1]); 40 | } 41 | } 42 | 43 | int query(int l, int r) { 44 | int ret = INF; 45 | for(l += M, r += M+1; l < r; l >>= 1, r >>= 1) { 46 | if(l & 1) ret = min(t[l++], ret); 47 | if(r & 1) ret = min(t[--r], ret); 48 | } 49 | return ret; 50 | } 51 | 52 | public: 53 | void solve(istream &cin, ostream &cout) { 54 | cin >> n >> k; 55 | cin >> s; 56 | for(int i = 0; i < n; i++) { 57 | S[i+1] = S[i] + (s[i] == 'H' ? 1 : -1); 58 | } 59 | for(int i = 0; i < 2*M; i++) t[i] = INF; 60 | ins(N, 0); 61 | for(int i = 1; i <= n; i++) { 62 | if(i >= k + 1) del(N + S[i - k - 1], dp[i - k - 1]); 63 | dp[i] = min(query(0, N + S[i] - 1), query(N + S[i], 2*N - 1) + 1); 64 | ins(N + S[i], dp[i]); 65 | } 66 | cout << dp[n]; 67 | } 68 | }; 69 | 70 | class Solver { 71 | public: 72 | void solve(std::istream& in, std::ostream& out) { 73 | redistricting *obj = new redistricting(); 74 | obj->solve(in, out); 75 | delete obj; 76 | } 77 | }; 78 | 79 | int main() { 80 | ios::sync_with_stdio(false); 81 | cin.tie(0); 82 | Solver solver; 83 | std::ifstream in("redistricting.in"); 84 | std::ofstream out("redistricting.out"); 85 | solver.solve(in, out); 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /Olympiad/infoarena/puncte.cpp: -------------------------------------------------------------------------------- 1 | // Expand formula and do CHT. Either Dynamic LiChao or we can sort the points and queries and use O(n) CHT. 2 | #include 3 | #define long long long 4 | using namespace std; 5 | const long LINF = LLONG_MAX, INF = 1e9+1; 6 | 7 | struct Line { 8 | long m, c; 9 | Line(long m, long c): m(m), c(c) {} 10 | long get(long x) { return m*x + c; } 11 | }; 12 | 13 | struct Node { 14 | Line v; 15 | Node *l, *r; 16 | Node(Line v): v(v), l(NULL), r(NULL) {} 17 | }; 18 | 19 | void update(Node* &t, long l, long r, Line v) { 20 | if(!t) { 21 | t = new Node(v); 22 | return; 23 | } 24 | if(t->v.get(l) < v.get(l) && t->v.get(r) < v.get(r)) return; 25 | if(l == r || t->v.get(l) > v.get(l) && t->v.get(r) > v.get(r)) { 26 | t->v = v; 27 | return; 28 | } 29 | long mid = l+r >> 1; 30 | if(t->v.get(mid) > v.get(mid)) swap(t->v, v); 31 | if((t->v.get(l) > v.get(l)) == (t->v.get(mid) > v.get(mid))) { 32 | update(t->r, mid+1, r, v); 33 | } else { 34 | update(t->l, l, mid, v); 35 | } 36 | } 37 | 38 | long query(Node *t, long l, long r, long x) { 39 | if(!t) return LINF; 40 | if(l == r) return t->v.get(x); 41 | long ret = t->v.get(x); 42 | long mid = l+r >> 1; 43 | if(x <= mid) { 44 | ret = min(query(t->l, l, mid, x), ret); 45 | } else { 46 | ret = min(query(t->r, mid+1, r, x), ret); 47 | } 48 | return ret; 49 | } 50 | 51 | long n, m; 52 | Node *root; 53 | 54 | int main() { 55 | ios::sync_with_stdio(false); 56 | cin.tie(0); 57 | ifstream cin("puncte.in"); 58 | ofstream cout("puncte.out"); 59 | cin >> n >> m; 60 | vector > lines; 61 | for(long i = 0; i < n; i++) { 62 | long x, y; 63 | cin >> x >> y; 64 | Line add = Line(-2ll * x, 1ll * x * x + 1ll * y * y); 65 | update(root, -INF, INF, add); 66 | } 67 | for(long i = 0; i < m; i++) { 68 | long x; 69 | cin >> x; 70 | cout << query(root, -INF, INF, x) + x * x << '\n'; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /PKU/temp.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galletas1712/CompetitiveProgramming/48f546f83bcab17211e9cea5a35edc1968344290/PKU/temp.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Solutions to competitive programming problemsets from online sources and Olympiads 2 | -------------------------------------------------------------------------------- /SPOJ/GOT.cpp: -------------------------------------------------------------------------------- 1 | // Easy Mo's on Tree or alternatively persistent segment tree. Wasted nearly three hours on a stupid swapping += with -= 2 | #include 3 | using namespace std; 4 | const int BLK = 300; 5 | 6 | struct query { 7 | int l, r, c, i; 8 | query() {} 9 | query(int l, int r, int c, int i): l(l), r(r), c(c), i(i) {} 10 | bool operator<(const query& rhs) const { 11 | return make_pair(l / BLK, r) < make_pair(rhs.l / BLK, rhs.r); 12 | } 13 | }; 14 | 15 | int n, q; 16 | vector > g; 17 | vector color, ord, st, ed, depth, cnt, state, ans; 18 | vector > anc; 19 | vector queries; 20 | 21 | void init_dfs(int u, int p) { 22 | ord.push_back(u); 23 | st[u] = ord.size() - 1; 24 | for(int v: g[u]) if(v != p) { 25 | depth[v] = depth[u] + 1; 26 | anc[v].push_back(u); 27 | for(int j = 0; 1 << j+1 <= depth[v]; j++) 28 | anc[v].push_back(anc[anc[v][j]][j]); 29 | init_dfs(v, u); 30 | } 31 | ord.push_back(u); 32 | ed[u] = ord.size() - 1; 33 | } 34 | 35 | int get_lca(int u, int v) { 36 | if(depth[v] > depth[u]) swap(u, v); 37 | for(int j = 0; depth[u] != depth[v]; j++) if(depth[u] - depth[v] >> j & 1) u = anc[u][j]; 38 | if(u == v) return u; 39 | for(int j = anc[u].size()-1; j >= 0; j--) if(j < anc[u].size() && anc[u][j] != anc[v][j]) 40 | u = anc[u][j], v = anc[v][j]; 41 | return anc[u][0]; 42 | } 43 | 44 | int main() { 45 | while(scanf("%d %d", &n, &q) != EOF) { 46 | g = vector >(n+1); 47 | ord.clear(); 48 | queries.clear(); 49 | color = vector(n+1); 50 | st = vector(n+1); 51 | ed = vector(n+1); 52 | depth = vector(n+1); 53 | anc = vector >(n+1); 54 | 55 | for(int i = 1; i <= n; i++) scanf("%d", &color[i]); 56 | 57 | for(int i = 1, u, v; i < n; i++) { 58 | scanf("%d %d", &u, &v); 59 | g[u].push_back(v); 60 | g[v].push_back(u); 61 | } 62 | init_dfs(1, -1); 63 | for(int i = 0, u, v, c; i < q; i++) { 64 | scanf("%d %d %d", &u, &v, &c); 65 | int lca = get_lca(u, v); 66 | if(st[u] > st[v]) swap(u, v); 67 | if(lca == u) queries.emplace_back(st[u], st[v], c, i); 68 | else { 69 | queries.emplace_back(ed[u], st[v], c, i); 70 | queries.emplace_back(st[lca], st[lca], c, i); 71 | assert(ed[u] <= st[v] && lca != v); 72 | } 73 | } 74 | sort(queries.begin(), queries.end()); 75 | cnt = vector(n+1); 76 | state = vector(n+1); 77 | ans = vector(q); 78 | int l = 0, r = 0; 79 | state[ord[0]] = 1; 80 | ++cnt[color[ord[0]]]; 81 | for(query qq: queries) { 82 | while(l < qq.l) { 83 | state[ord[l]] ^= 1; 84 | cnt[color[ord[l]]] += (state[ord[l]] ? 1 : -1); 85 | ++l; 86 | } 87 | while(r > qq.r) { 88 | state[ord[r]] ^= 1; 89 | cnt[color[ord[r]]] += (state[ord[r]] ? 1 : -1); 90 | --r; 91 | } 92 | while(l > qq.l) { 93 | --l; 94 | state[ord[l]] ^= 1; 95 | cnt[color[ord[l]]] += (state[ord[l]] ? 1 : -1); 96 | } 97 | while(r < qq.r) { 98 | ++r; 99 | state[ord[r]] ^= 1; 100 | cnt[color[ord[r]]] += (state[ord[r]] ? 1 : -1); 101 | } 102 | ans[qq.i] |= cnt[qq.c]; 103 | } 104 | for(int i = 0; i < q; i++) printf("%s\n", (ans[i] ? "Find" : "NotFind")); 105 | printf("\n"); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /SPOJ/INCDSEQ.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define long long long 3 | using namespace std; 4 | const int N = 1e4+10; 5 | const long MOD = 5e6; 6 | 7 | int n, K, a[N]; 8 | long dp[N][51], f[N][51]; 9 | 10 | void update(int i, int k, long v) { 11 | ++i; 12 | while(i < N) f[i][k] = (f[i][k] + v) % MOD, i += i & -i; 13 | } 14 | 15 | long query(int i, int k) { 16 | long ret = 0; 17 | ++i; 18 | while(i > 0) { 19 | ret = (ret + f[i][k]) % MOD; 20 | i -= i & -i; 21 | } 22 | return ret; 23 | } 24 | 25 | void compress() { 26 | vector vals; 27 | vals.push_back(-1); 28 | for(int i = 1; i <= n; i++) vals.push_back(a[i]); 29 | sort(vals.begin(), vals.end()); 30 | vals.resize(unique(vals.begin(), vals.end()) - vals.begin()); 31 | unordered_map mp; 32 | for(int i = 0; i < vals.size(); i++) mp[vals[i]] = i; 33 | for(int i = 1; i <= n; i++) a[i] = mp[a[i]]; 34 | } 35 | 36 | int main() { 37 | ios::sync_with_stdio(false); 38 | cin.tie(0); 39 | cin >> n >> K; 40 | for(int i = 1; i <= n; i++) cin >> a[i]; 41 | compress(); 42 | for(int i = 1; i <= n; i++) { 43 | for(int k = 1; k <= K; k++) { 44 | long diff = ((k > 1 ? query(a[i]-1, k-1) : 1) - dp[a[i]][k] + MOD) % MOD; 45 | dp[a[i]][k] = (dp[a[i]][k] + diff) % MOD; 46 | update(a[i], k, diff); 47 | } 48 | } 49 | cout << (query(N-1, K) + MOD) % MOD << endl; 50 | } 51 | -------------------------------------------------------------------------------- /SPOJ/MCAMP.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | 9 | class MCAMP { 10 | int n; 11 | vector x, es, gs; 12 | public: 13 | void solve(istream& cin, ostream& cout) { 14 | cin >> n; 15 | x = vector(n+1); 16 | es = vector(n+1); 17 | gs = vector(n+1); 18 | vector > ord; 19 | for(int i = 1; i <= n; i++) { 20 | cin >> x[i] >> gs[i] >> es[i]; 21 | es[i] += es[i-1]; 22 | gs[i] += gs[i-1]; 23 | ord.emplace_back(-(x[i] - es[i-1]), i, 0); 24 | ord.emplace_back(-(x[i] - es[i]), i, 1); 25 | } 26 | sort(ord.begin(), ord.end()); 27 | int j = INF; 28 | long ans = 0; 29 | for(auto tt: ord) { 30 | int i, type; 31 | tie(ignore, i, type) = tt; 32 | if(type == 0) j = min(i, j); 33 | else if(j <= i) ans = max(gs[i] - gs[j-1], ans); 34 | } 35 | cout << ans; 36 | } 37 | }; 38 | 39 | 40 | 41 | int main() { 42 | ios::sync_with_stdio(false); 43 | cin.tie(0); 44 | MCAMP solver; 45 | std::istream& in(std::cin); 46 | std::ostream& out(std::cout); 47 | solver.solve(in, out); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /SPOJ/SUBLEX.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define long long long 4 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 5 | const int INF = 1e9+1; 6 | const double EPS = 1e-10; 7 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 8 | const int N = 1e5+1; 9 | 10 | class SUBLEX { 11 | 12 | int n, q, k, sa[N], pos[N], tmp[N], lcp[N]; 13 | long f[N]; 14 | char s[N]; 15 | 16 | void buildSA() { 17 | int gap; 18 | for(int i = 0; i < n; i++) sa[i] = i, pos[i] = s[i]; 19 | auto cmp = [&] (int i, int j) { 20 | if(pos[i] != pos[j]) return pos[i] < pos[j]; 21 | i += gap, j += gap; 22 | return i < n && j < n ? pos[i] < pos[j] : i > j; 23 | }; 24 | for(gap = 1; ; gap <<= 1) { 25 | sort(sa, sa + n, cmp); 26 | for(int i = 1; i < n; i++) tmp[i] = tmp[i-1] + cmp(sa[i-1], sa[i]); 27 | for(int i = 0; i < n; i++) pos[sa[i]] = tmp[i]; 28 | if(tmp[n - 1] == n - 1) break; 29 | } 30 | } 31 | 32 | void kasai() { 33 | for(int i = 0, k = 0; i < n; i++, k = (k ? k - 1 : 0)) { 34 | if(pos[i] == n - 1) { 35 | k = 0; 36 | continue; 37 | } 38 | int j = sa[pos[i] + 1]; 39 | while(i + k < n && j + k < n && s[i + k] == s[j + k]) ++k; 40 | lcp[pos[i]] = k; 41 | } 42 | } 43 | 44 | public: 45 | void solve(istream &cin, ostream &cout) { 46 | cin >> s; 47 | n = strlen(s); 48 | buildSA(); 49 | kasai(); 50 | f[0] = n - sa[0]; 51 | for(int i = 1; i < n; i++) { 52 | f[i] = n - sa[i] - lcp[i-1]; 53 | } 54 | for(int i = 1; i < n; i++) f[i] += f[i-1]; 55 | cin >> q; 56 | while(q--) { 57 | int k; 58 | cin >> k; 59 | int l = 0, r = n - 1; 60 | while(l < r) { 61 | int mid = l+r >> 1; 62 | if(f[mid] >= k) r = mid; 63 | else l = mid + 1; 64 | } 65 | int ed = n - (f[l] - k); 66 | for(int i = sa[l]; i < ed; i++) cout << s[i]; 67 | cout << '\n'; 68 | } 69 | } 70 | }; 71 | 72 | class Solver { 73 | public: 74 | void solve(std::istream& in, std::ostream& out) { 75 | SUBLEX *obj = new SUBLEX(); 76 | obj->solve(in, out); 77 | delete obj; 78 | } 79 | }; 80 | 81 | int main() { 82 | ios::sync_with_stdio(false); 83 | cin.tie(0); 84 | Solver solver; 85 | std::istream& in(std::cin); 86 | std::ostream& out(std::cout); 87 | solver.solve(in, out); 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /TJU/temp.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galletas1712/CompetitiveProgramming/48f546f83bcab17211e9cea5a35edc1968344290/TJU/temp.txt -------------------------------------------------------------------------------- /Techjam/A.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * code generated by JHelper 3 | * More info: https://github.com/AlexeyDmitriev/JHelper 4 | * @author szawinis 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #define long long long 12 | #define pii pair 13 | #define x first 14 | #define y second 15 | using namespace std; 16 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 17 | const int INF = 1e9+1; 18 | const double EPS = 1e-10; 19 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 20 | 21 | class TJ_A { 22 | private: 23 | int n, m; 24 | vector V; 25 | long cross(pii a, pii b, pii c) { 26 | return (c.y - a.y) * (b.x - a.x) - (b.y - a.y) * (c.x - a.x); 27 | } 28 | public: 29 | void solve(istream& cin, ostream& cout) { 30 | auto cmp = [&](const pii &a, const pii &b) { 31 | return (a.y - V[0].y) * (b.x - V[0].x) <= (b.y - V[0].y) * (a.x - V[0].x); 32 | }; 33 | cin >> n; 34 | for(int i = 0; i < n; ++i) { 35 | long a, b; 36 | cin >> a >> b; 37 | V.emplace_back(a, b); 38 | } 39 | for(int i = 1; i < n; ++i) if(V[i].y < V[0].y) swap(V[i], V[0]); 40 | sort(V.begin()+1, V.end(), cmp); 41 | cin >> m; 42 | while(m--) { 43 | long x, y; cin >> x >> y; 44 | if(y < V[0].y) { 45 | cout << "Outside" << endl; 46 | continue; 47 | } 48 | if(y == V[0].y) { 49 | if(pii(x, y) == V[0]) cout << "On the boundary" << endl; 50 | continue; 51 | } 52 | int l = 0, r = n-1; 53 | while(l < r) { 54 | int m = l + r + 1 >> 1; 55 | if(cmp(V[m], pii(x, y))) l = m; 56 | else r = m-1; 57 | } 58 | pii a = V[r], b = V[(r+1) % n], c = pii(x, y); 59 | long val = cross(a, b, c); 60 | if(val == 0) cout << "On the boundary" << endl; 61 | else if(val < 0) cout << "Outside" << endl; 62 | else cout << "Inside" << endl; 63 | } 64 | } 65 | }; 66 | 67 | int main() { 68 | ios::sync_with_stdio(false); 69 | cin.tie(0); 70 | TJ_A solver; 71 | std::istream& in(std::cin); 72 | std::ostream& out(std::cout); 73 | solver.solve(in, out); 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /Techjam/C.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * code generated by JHelper 3 | * More info: https://github.com/AlexeyDmitriev/JHelper 4 | * @author szawinis 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | using namespace std; 12 | #define long long long 13 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 14 | const int INF = 1e9+1; 15 | const double EPS = 1e-10; 16 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 17 | const int N = 1e3+5; 18 | 19 | 20 | class TJ_C { 21 | int n, P; 22 | vector g[N]; 23 | vector vec; 24 | int sz[N]; 25 | void get_sz(int u, int p) { 26 | sz[u] = 1; 27 | if(p)g[u].erase(find(g[u].begin(), g[u].end(), p)); 28 | for(int &v : g[u]) { 29 | get_sz(v, u), sz[u] += sz[v]; 30 | if(sz[v] > sz[g[u][0]]) swap(v, g[u][0]); 31 | } 32 | } 33 | vector dfs(int u, int p) { 34 | vector dp; 35 | if(g[u].empty()) dp = vector(vec.size(), 1); 36 | else dp = dfs(g[u][0], u); 37 | for(int i = 1; i + i < vec.size(); ++i) swap(dp[i], dp[vec.size()-i]); 38 | dp[0] = 0; 39 | for(int v : g[u]) if(v != g[u][0]) { 40 | vector ret = dfs(v, u); 41 | for(int i = 1; i < vec.size(); i++) { 42 | dp[i] = (dp[i] * ret[((int)vec.size())-i]) % MOD; 43 | } 44 | } 45 | for(int i = 1; i < vec.size(); ++i) { 46 | dp[i] = (dp[i] * (vec[i] - vec[i-1]) + dp[i-1]) % MOD; 47 | } 48 | return dp; 49 | } 50 | public: 51 | void solve(istream& cin, ostream& cout) { 52 | cin >> n >> P; 53 | for(int i = 1; i * i <= P; ++i) { 54 | vec.emplace_back(i), vec.emplace_back(P/i); 55 | } 56 | vec.emplace_back(0); 57 | sort(vec.begin(), vec.end()); 58 | vec.resize(unique(vec.begin(), vec.end()) - vec.begin()); 59 | for(int i = 1, u, v; i < n; i++) { 60 | cin >> u >> v; 61 | g[u].emplace_back(v), g[v].emplace_back(u); 62 | } 63 | get_sz(1, 0); 64 | cout << dfs(1, 0).back() << endl; 65 | } 66 | }; 67 | 68 | int main() { 69 | ios::sync_with_stdio(false); 70 | cin.tie(0); 71 | TJ_C solver; 72 | std::istream& in(std::cin); 73 | std::ostream& out(std::cout); 74 | solver.solve(in, out); 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /Techjam/D.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * code generated by JHelper 3 | * More info: https://github.com/AlexeyDmitriev/JHelper 4 | * @author szawinis 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #define pii pair 12 | #define x first 13 | #define y second 14 | using namespace std; 15 | #define long long long 16 | const long MOD = 1e9+7, LINF = 1e18 + 1e16; 17 | const int INF = 1e9+1; 18 | const double EPS = 1e-10; 19 | const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 20 | const int N = 105; 21 | 22 | class TJ_D { 23 | private: 24 | int n; 25 | int A[N]; 26 | vector que; 27 | int pos[N]; 28 | int ret[N]; 29 | void genpos() { 30 | for(int i = 1; i <= n; ++i) pos[A[i]] = i; 31 | } 32 | void swp(int l, int r) { 33 | que.emplace_back(l, r); 34 | int ptr = 1; 35 | for(int i = r+1; i <= n; ++i) ret[ptr++] = A[i]; 36 | for(int i = l; i <= r; ++i) ret[ptr++] = A[i]; 37 | for(int i = 1; i < l; ++i) ret[ptr++] = A[i]; 38 | for(int i = 1; i <= n; ++i) A[i] = ret[i]; 39 | genpos(); 40 | } 41 | public: 42 | void solve(istream& cin, ostream& cout) { 43 | cin >> n; 44 | vector vec; 45 | for(int i = 1; i <= n; ++i) { 46 | cin >> A[i]; 47 | vec.emplace_back(A[i], i); 48 | } 49 | sort(vec.begin(), vec.end()); 50 | for(int i = 0; i < vec.size(); ++i) A[vec[i].y] = i+1; 51 | genpos(); 52 | if(A[1] != 1) 53 | swp(1, pos[1]-1); 54 | for(int i = 2; i < n; ++i) { 55 | if(A[i] == i) continue; 56 | swp(i, pos[i]-1); 57 | swp(1, n-i+1); 58 | } 59 | cout << que.size() << endl; 60 | for(auto x : que) cout << x.x << ' ' << x.y << endl; 61 | } 62 | }; 63 | 64 | int main() { 65 | ios::sync_with_stdio(false); 66 | cin.tie(0); 67 | TJ_D solver; 68 | std::istream& in(std::cin); 69 | std::ostream& out(std::cout); 70 | solver.solve(in, out); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /Timus/temp.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galletas1712/CompetitiveProgramming/48f546f83bcab17211e9cea5a35edc1968344290/Timus/temp.txt -------------------------------------------------------------------------------- /TopCoder/SRM465-D1-600.cpp: -------------------------------------------------------------------------------- 1 | // Reduce to minimum weight bipartite vertex cover 2 | // Can be solved using maximum flow, by using a similar network to bipartite maximum cardinality matching 3 | #include 4 | using namespace std; 5 | const int INF = 1e9+1; 6 | 7 | struct edge { 8 | int u, v, cap, flow; 9 | edge(int u, int v, int cap): u(u), v(v), cap(cap), flow(0) {} 10 | }; 11 | 12 | struct GreenWarfare { // s = n-2, t = n-1; 13 | int n; 14 | vector ptr, lvl; 15 | vector > g; 16 | vector edges; 17 | 18 | bool bfs() { 19 | queue q; 20 | lvl = vector(n, -1); 21 | q.push(n-2); 22 | lvl[n-2] = 0; 23 | while(!q.empty()) { 24 | int u = q.front(); 25 | q.pop(); 26 | for(int e: g[u]) if(edges[e].cap - edges[e].flow > 0 && lvl[edges[e].v] == -1) { 27 | lvl[edges[e].v] = lvl[u] + 1; 28 | q.push(edges[e].v); 29 | } 30 | } 31 | return lvl[n-1] != -1; 32 | } 33 | int dfs(int u, int pushed) { 34 | if(!pushed) return 0; 35 | if(u == n-1) return pushed; 36 | for(; ptr[u] < int(g[u].size()); ++ptr[u]) { 37 | int e = g[u][ptr[u]]; 38 | int v = edges[e].v; 39 | if(edges[e].cap - edges[e].flow <= 0 || lvl[v] != lvl[u] + 1) continue; 40 | int possible_push = dfs(v, min(pushed, edges[e].cap - edges[e].flow)); 41 | edges[e].flow += possible_push; 42 | edges[e^1].flow -= possible_push; 43 | if(possible_push) return possible_push; 44 | } 45 | return 0; 46 | } 47 | void add_edge(int u, int v, int cap) { 48 | edges.emplace_back(u, v, cap); 49 | edges.emplace_back(v, u, 0); 50 | g[u].push_back(edges.size() - 2); 51 | g[v].push_back(edges.size() - 1); 52 | } 53 | 54 | int dist2(int x1, int y1, int x2, int y2) { 55 | return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); 56 | } 57 | int minimumEnergyCost(vector canonX, vector canonY, vector baseX, vector baseY, vector plantX, vector plantY, int energySupplyRadius) { 58 | n = int(baseX.size()) + int(plantX.size()) + 2; 59 | g = vector >(n); 60 | ptr = vector(n, 0); 61 | vector baseE(int(baseX.size()), INF), plantE(int(plantX.size()), INF); 62 | 63 | for(int i = 0; i < int(baseX.size()); i++) { 64 | for(int j = 0; j < int(canonX.size()); j++) { 65 | baseE[i] = min(dist2(baseX[i], baseY[i], canonX[j], canonY[j]), baseE[i]); 66 | } 67 | } 68 | for(int i = 0; i < int(plantX.size()); i++) { 69 | for(int j = 0; j < int(canonX.size()); j++) { 70 | plantE[i] = min(dist2(plantX[i], plantY[i], canonX[j], canonY[j]), plantE[i]); 71 | } 72 | } 73 | for(int i = 0; i < int(baseX.size()); i++) add_edge(n-2, i, baseE[i]); 74 | for(int i = 0; i < int(plantX.size()); i++) add_edge(int(baseX.size()) + i, n-1, plantE[i]); 75 | for(int i = 0; i < int(baseX.size()); i++) for(int j = 0; j < int(plantX.size()); j++) 76 | if(dist2(baseX[i], baseY[i], plantX[j], plantY[j]) <= energySupplyRadius * energySupplyRadius) 77 | add_edge(i, int(baseX.size()) + j, INF); 78 | int ans = 0; 79 | while(bfs()) { 80 | ptr = vector(n, 0); 81 | while(int pushed = dfs(n-2, INF)) ans += pushed; 82 | } 83 | return ans; 84 | } 85 | }; 86 | -------------------------------------------------------------------------------- /TopCoder/temp.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galletas1712/CompetitiveProgramming/48f546f83bcab17211e9cea5a35edc1968344290/TopCoder/temp.txt -------------------------------------------------------------------------------- /UVA/UVA1194.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Reduce problem to bipartite minimum vertex cover (ignoring 0 vertex) 3 | By Konig's theorem, this is equivalent to maximum bipartite matching 4 | We run our handy maximum bipartite matching algorithm using geeksforgeeks implementation 5 | This is O(VE) because Ford-Fulkerson runs in O(E * max flow), where max flow is V since the maximum possible bipartite matching is V 6 | V = m + n 7 | E = K 8 | So runs in O(K(m + n)) time, which is very fast! 9 | */ 10 | #include 11 | using namespace std; 12 | 13 | bool rec(int u, vector &seen, vector &rev_match, vector > g) { 14 | for(int v: g[u]) if(!seen[v]) { 15 | seen[v] = true; 16 | if(rev_match[v] == -1 || rec(rev_match[v], seen, rev_match, g)) { 17 | rev_match[v] = u; 18 | return true; 19 | } 20 | } 21 | return false; 22 | } 23 | 24 | void solve(int n, int m, int k) { 25 | vector a(k), b(k); 26 | vector > g(n); 27 | for(int i = 0; i < k; i++) { 28 | cin >> i >> a[i] >> b[i]; 29 | if(a[i] && b[i]) g[a[i]].push_back(b[i]); 30 | } 31 | vector rev_match(m, -1); 32 | int ans = 0; 33 | for(int i = 0; i < n; i++) { 34 | vector seen(m); 35 | ans += rec(i, seen, rev_match, g); 36 | } 37 | cout << ans << '\n'; 38 | } 39 | 40 | int main() { 41 | ios::sync_with_stdio(false); 42 | cin.tie(0); 43 | while(true) { 44 | int n, m, k; 45 | cin >> n; 46 | if(n == 0) break; 47 | cin >> m >> k; 48 | solve(n, m, k); 49 | } 50 | } 51 | --------------------------------------------------------------------------------