-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathblueprint.cpp
More file actions
324 lines (265 loc) · 10.6 KB
/
blueprint.cpp
File metadata and controls
324 lines (265 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
#pragma GCC optimize ("O3")
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <algorithm>
#include <list>
#include <vector>
#include <array>
#include <set>
#include <map>
#include <unordered_map>
#include <numeric>
#include <bitset>
#include <queue>
#include <stack>
using namespace std;
#define FOR(i,a,b) for (long i = (a); i < (b); i++)
#define FORR(i,a,b) for (long i = (b)-1; i >= (a); i--)
#define all(x) (x).begin(), (x).end()
#define MAX(cont) *max_element(all((cont)))
#define MIN(cont) *min_element(all((cont)))
#define ARGMAX(cont) max_element(all((cont))) - (cont).begin()
#define ARGMIN(cont) min_element(all((cont))) - (cont).begin()
#define MAXLONG 9223372036854775807L
#define MINLONG -9223372036854775808L
typedef pair<long, long> pll;
typedef vector<long> vl;
typedef vector<vector<long>> ml;
template<typename T>
using matrix = vector<vector<T>>;
template<class Container>
void printc(const Container &cont){
for (auto e: cont) cout << e << " "; cout << endl;
}
template<class TH> void _dbg(const char *sdbg, TH h){ cerr<<sdbg<<'='<<h<<endl; }
template<class TH> void _dbg(const char *sdbg, const vector<TH> &vec){
cerr<<sdbg<<'=';
for (TH e: vec) cerr << e << " "; cerr << endl;
}
template<class TH> void _dbg(const char *sdbg, const vector<vector<TH>> &mat){
cerr<<sdbg<<'='<< endl;
for(vector<TH> vec: mat){for(TH e: vec) cerr << e << " "; cerr << endl;}
}
template<class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
while(*sdbg!=',')cerr<<*sdbg++;
cerr<<'='<<h<<','<<' '; _dbg(sdbg+1, a...);
}
#define print(...) _dbg(#__VA_ARGS__, __VA_ARGS__);
// Things to be aware of:
// Accesing a map or set with i = map[k] will add that element into the set with default value
// Always make sure to read everything in before printing and returning a solution!!!!!
// In case of circular function references, declare an empty function at the top e.g. long func(long k);
// reassigning containers, e.g. vl vec2 = vec makes a copy.
// get iterator pointer via &(*iter)
// use g++sane for debugging, it catches array out of bound shenanigans
// you can do an ultimate return with a try / catch block, use throw 1;
// map is always ordered according to key
// always assume the worst :D use MAX and MIN for boundaries of long
// long a = 1; max(0,a); fails as max is on long and int
// for interactove problems write a function "query", which sends and reads at the same time
// Usually copies are inserted into containers or functions, pass by reference if needed
// Erasing in a container by iterator causes errors in g++6.3 e.g. list.erase(iter), use iter++ and account for increment
// Be aware of functions with mod returning negative remainders
// print(...) macro can slow down the program
// TODO how to transfrom string quickly to vector of chars? How to compare strings?
// TODO checkout other containers and see what alogriths there are in algorithm
// TODO checkout cmath
// TODO checkout bitset
int main() {
ios_base::sync_with_stdio(false);
// ================================================================
// containers and strings
// ================================================================
{
// Reverse for loop, print works without colon
FORR(x,0,10){
// print(x)
}
// Initialization and lexiographic sort of matrix
ml mat = ml(5, vl(10,0));
sort(all(mat));
print(mat);
// Initializes a vector and populates with incrementing values starting from offset
vl vec(10,0);
iota(all(vec), 3);
printc(vec);
// How to create pairs and tuples
pll p{1,'c'}; // autmatic cast to proper type
tuple<long, string> t{1, "abc"};
auto t2 = make_tuple(2,"def", 5); // types are int and const char*
tuple<long, string, long> t3 = make_tuple(3,"ghi", 10);
// acessing elements of pair and tuple
print(p.second)
print(get<0>(t)) // acces by index
print(get<const char*> (t2))
print(get<string> (t3)) // acces by type only works when it's unambiguous
// Creating and iterating through lists
list<long> ll{1,2,3,4,5,6};
for (auto it = next(ll.begin()); it != prev(ll.end()); it++) { // The modifier next and prev are optional
if (*it == 2) ll.erase(it); // erasing element, still every element is visited once by iterator
if (*it == 3) ll.insert(it, 12); // inserting element just before current iterator position,
if (*it == 4) *it = 22; // replacing element
}
printc(ll);
// Creating and manipulating maps, sets and unordered_maps
unordered_map<string, long> umap{{"a", 1}}; // similar to map with constant acess time, items are pairs
umap.insert({"b", 2});
umap.count("c"); // 1 or 0, use that to check for presence of element, don't use umap["c"]
umap["d"]; // if not present, will add with default value, even during access time, so be careful.
for (auto p: umap) print(p.first, p.second);
// creating and manipulating strings, strings are mutable
string s = "abcdefghijklmnopqrstuvwxyz";
print(s.substr(10, 5)) // get subtring by start and length
s.resize(30, '0'); // cut to first n or fill until n chars
s.erase(10, 5); // erase section starting from 10 of length 5, opposit of subtr
print(s)
string s2 = "***sdf*sdfa*sdf";
vector<string> vs;
long index;
while (true){
index = s2.find("*");
if (index < 0){
vs.push_back(s2);
break;
}
vs.push_back(s2.substr(0, index));
s2.erase(0, index+1);
}
printc(vs);
}
// ================================================================
// algorithms
// ================================================================
// checkout http://www.cplusplus.com/reference/algorithm/ and https://en.cppreference.com/w/cpp/numeric
{
vl vec{1,4,2,3};
vl vec2{4,2};
long maxi = MAX(vec); // get maximum of vector
long argmax = ARGMAX(vec); // get maximum index
long argmin = min_element(all(vec)) - vec.begin(); // get minimum index, ARGMIN would work too
string s = "asdfjklasdf"; // algorithm works just fine for strings
char max_char = *max_element(all(s));
long argmax_char = ARGMAX(s);
bool all_true = all_of(all(vec), [](long l) {return l>0;}); // similarly any_of, none_of, also works for non-lambda functions
count(all(s), 'a'); // counts the number of occurances of element in container
bool equal = vec == vec2; // check for equality of vectors
long index_begin = search(all(vec), all(vec2)) - vec.begin(); // returns index to first occurence of vec2 in vec
}
// ================================================================
// cmath and numeric
// ================================================================
// checkout http://www.cplusplus.com/reference/cmath/ and
{
long power_long = powl(2,10); // power function for integers
}
// ================================================================
// playground and stuff
// ================================================================
{
}
}
long gcd(long a, long b){
// careful, will return negative factors for negative arguments
if (b == 0) return a;
return gcd(b, a%b);
}
// Edmond Karp algorithm to solve maxflow
// changes capacity matrix!
// adj contains all children and parents of a node
// cap contains the capacity of all vertex combinations, always non-negative
// s and t denote source and sink identifier
pair<vl, long> bfs(long s, long t, vector<vector<long>> &adj, ml &cap){
long num_nodes = adj.size();
vl parents(num_nodes, -1);
parents[s] = -2; // we don't want to go back to source
queue<pll> node_flows;
node_flows.push({s, MAXLONG});
long cur, flow, next_flow;
while(!node_flows.empty()){
cur = node_flows.front().first;
flow = node_flows.front().second;
node_flows.pop();
for (long next: adj[cur]){
if(parents[next] == -1 && cap[cur][next]){
parents[next] = cur;
next_flow = min(flow, cap[cur][next]);
node_flows.push({next, next_flow});
if (next == t) {
return make_pair(parents, next_flow);
}
}
}
}
return make_pair(parents, 0L);
}
long maxflow(long s, long t, vector<vector<long>> &adjacent, ml &capacity){
long total_flow = 0;
long prev, cur;
while(true){
pair<vl, long> search = bfs(s,t,adjacent,capacity);
vl parents = search.first;
long flow = search.second;
if (!flow) return total_flow;
total_flow += flow;
cur = t;
while(cur != s){
prev = parents[cur];
capacity[prev][cur] -= flow;
capacity[cur][prev] += flow;
cur = prev;
}
}
}
// Fenwick tree update and add
// vec represents ft tree and is one longer than arr
// arr contains the raw elements for underlying tree
void update(long i, long v, vl &vec, vl &arr){
i++;
long size = vec.size();
long d = v - arr[i];
arr[i] = v;
while (i < size){
vec[i] += d;
i += i & -i;
}
}
long add(long i, vl &vec){ // returns 0 for i = 0;
long size = vec.size();
long total = 0;
while(i > 0){
total += vec[i];
i -= i & -i;
}
return total;
}
// Kosaraju's algorithm for strongly connected components
// in contains the parents, out contains children for node at respective index
// returns vector with each entry marking the node index of a representative in component
void visit(long n, vector<vl> &out, vl &visited, stack<long> &finished){
if (visited[n]) return;
visited[n] = 1;
for (long c: out[n]) visit(c, out, visited, finished);
finished.push(n);
}
void assign(long n, long u, vector<vl> &in, vl &visited, vl &who){
if (!visited[n]) return;
visited[n] = 0;
who[n] = u;
for (long p: in[n]) assign(p, u, in, visited, who);
}
vl strongly_connected(vector<vl> &in, vector<vl> &out){
long num_nodes = in.size(); // make sure in contains parents for all nodes
vl visited(num_nodes);
vl who(num_nodes);
stack<long> finished;
FOR(n,0,num_nodes) visit(n, out, visited, finished);
while(!finished.empty()) {
long n = finished.top();
finished.pop();
assign(n,n, in, visited, who);
}
return who;
}