notebook
notebook
Mottakin Chowdhury
November 6, 2018
1
2
7.13 Russian Peasant Multiplication . . . . . . . . . . . . . . . . . . . . 132 return Q ? p < o.p : k < o.k;
7.14 Stable Marriage Problem . . . . . . . . . . . . . . . . . . . . . . . 133 }
7.15 Thomas Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 };
7.16 U128 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
struct LineContainer : multiset<Line> {
7.17 Useful Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
const ll inf = LLONG_MAX;
7.18 int128 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
ll div(ll a, ll b) { // floored division
if (b < 0) a *= -1, b *= -1;
8 Notes 137 if (a >= 0) return a / b;
return -((-a + b - 1) / b);
9 String 137 }
9.1 A KMP Application . . . . . . . . . . . . . . . . . . . . . . . . . . 137
9.2 Aho Corasick 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 // updates x->p, determines if y is unneeded
9.3 Aho Corasick Occurrence Relation . . . . . . . . . . . . . . . . . . 139 bool isect(iterator x, iterator y) {
9.4 Aho Corasick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 if (y == end()) { x->p = inf; return 0; }
9.5 Double Hash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
9.6 Dynamic Aho Corasick Sample . . . . . . . . . . . . . . . . . . . . 142 else x->p = div(y->m - x->m, x->k - y->k);
9.7 Dynamic Aho Corasick . . . . . . . . . . . . . . . . . . . . . . . . . 144 return x->p >= y->p;
}
9.8 KMP 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.9 KMP 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 void add(ll k, ll m) {
9.10 Manacher-s Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . 148 auto z = insert({k, m, 0}), y = z++, x = y;
9.11 Minimum Lexicographic Rotation . . . . . . . . . . . . . . . . . . . 148 while (isect(y, z)) z = erase(z);
9.12 Palindrome Factorization . . . . . . . . . . . . . . . . . . . . . . . 149 if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
9.13 Palindromic Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 while ((y = x) != begin() && (--x)->p >= y->p) isect(x,
9.14 String Split by Delimiter . . . . . . . . . . . . . . . . . . . . . . . . 151 erase(y));
9.15 Suffix Array 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 }
9.16 Suffix Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
ll query(ll x) { // gives max value
9.17 Suffix Automata 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
assert(!empty());
9.18 Suffix Automata . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
Q = 1; auto l = *lower_bound({0, 0, x}); Q = 0;
9.19 Trie 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 return l.k * x + l.m;
9.20 Trie 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 }
9.21 Z Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 };
string A, B; int m, d;
ll dp[2002][2002][2][2];
1.5 Divide and Conquer DP
ll calc(int idx, int Mod, bool s, bool b)
{ // http://codeforces.com/blog/entry/8219
if(idx==B.size()) return Mod==0; // Divide and conquer optimization:
// Original Recurrence
if(dp[idx][Mod][s][b]!=-1) // dp[i][j] = min(dp[i-1][k] + C[k][j]) for k < j
return dp[idx][Mod][s][b]; // Sufficient condition:
// A[i][j] <= A[i][j+1]
ll ret=0; // where A[i][j] = smallest k that gives optimal answer
// How to use:
int low=s ? 0 : A[idx]-’0’; // // compute i-th row of dp from L to R. optL <= A[i][L] <= A[i][R] <=
int high=b ? 9 : B[idx]-’0’; optR
// compute(i, L, R, optL, optR)
for(int i=low; i<=high; i++) // 1. special case L == R
{ // 2. let M = (L + R) / 2. Calculate dp[i][M] and opt[i][M] using
if(idx%2 && i!=d) continue; O(optR - optL + 1)
if(idx%2==0 && i==d) continue; // 3. compute(i, L, M-1, optL, opt[i][M])
// 4. compute(i, M+1, R, opt[i][M], optR)
ret=(ret+calc(idx+1, (Mod*10+i)%m, s || i>low, b ||
i<high))%mod; // Example: http://codeforces.com/contest/321/problem/E
#include "../template.h"
// if(ret>=mod) ret-=mod;
} const int MN = 4011;
const int inf = 1000111000;
return dp[idx][Mod][s][b]=ret; int n, k;
} ll cost[MN][MN], dp[811][MN];
{ int main()
HullDynamic hd; {
vector<ll> curr(n+1,1e18); ms(dp,-1);
cin>>a>>b;
FOR(j,1,n+1) prnt(editDistance(a.size(),b.size()));
{ return 0;
ll m=2*a[j]; }
ll c=-a[j]*a[j]-dp[j-1];
hd.insert_line(m,c);
ll now=-hd.eval(a[j])+a[j]*a[j];
curr[j]=now; 1.8 IOI Aliens by koosaga
}
dp=curr;
#include <bits/stdc++.h>
}
using namespace std;
prnt(dp[n]);
typedef long long lint;
typedef pair<lint, lint> pi;
return 0;
const int MAXN = 100005;
}
vector<pi> v;
pi dp[MAXN];
1.7 Edit Distance Recursive struct point{
lint first;
int dp[34][34]; lint second;
string a, b; int cnt;
};
int editDistance(int i, int j)
{ struct cht{
if (dp[i][j]!=-1) vector<point> v;
return dp[i][j]; void clear(){ v.clear(); }
if (i==0) long double cross(point a, point b){
return dp[i][j]=j; return ((long double)(b.second - a.second) / (b.first -
if (j==0) a.first));
return dp[i][j]=i; }
void add_line(int x, lint y, int z){
int cost; while(v.size() >= 2 && cross(v[v.size()-2], v.back()) >
if (a[i-1]==b[j-1]) cross(v.back(), (point){x, y, z})){
cost=0; v.pop_back();
else }
cost=1; v.push_back({x, y, z});
return }
dp[i][j]=min(editDistance(i-1,j)+1,min(editDistance(i,j-1)+1, pi query(int x){
editDistance(i-1,j-1)+cost)); int s = 0, e = v.size()-1;
} auto f = [&](int p){
return v[p].first * x + v[p].second;
9
}
// Precalculate prefix-max and suffix-max values int main()
// max(prefix[u][j],suffix[u][j]) contains the maximum {
// value of f[u] if jth child was deleted while(scanf("%d", &n)!=EOF)
void goforfun(int u, int p=-1) {
{ int u, w;
FOR(j,0,graph[u].size()) FOR(i,2,n+1)
{ {
int v=graph[u][j].first; scanf("%d%d", &u, &w);
int w=graph[u][j].second;
graph[u].pb(MP(i,w));
if(v==p) continue; graph[i].pb(MP(u,w));
goforfun(v,u); }
goforfun(1);
f[u]=max(f[u],f[v]+w); goforgun(1);
} FOR(i,1,n+1) prnt(ans[i]);
int pref=0, suff=0; clear();
FOR(j,0,graph[u].size()) }
{ return 0;
int v=graph[u][j].first; }
int w=graph[u][j].second;
// important, we want to keep same size but avoid parent
if(v==p)
{ 1.10 Knuth Optimization
prefix[u].pb(0);
continue;
/*This trick works only for optimization DP over substrings for which
}
optimal
prefix[u].pb(pref);
middle point depends monotonously on the end points. Let mid[L,R] be the
pref=max(pref,f[v]+w);
first
}
middle point for (L,R) substring which gives optimal result. It can be
FORr(j,graph[u].size()-1,0)
proven
{
that mid[L,R-1] <= mid[L,R] <= mid[L+1,R] - this means monotonicity of
int v=graph[u][j].first;
mid by
int w=graph[u][j].second;
L and R. Applying this optimization reduces time complexity from O(k^3)
if(v==p)
to O(k^2)
{
because with fixed s (substring length) we have m_right(L) = mid[L+1][R]
suffix[u].pb(0);
= m_left(L+1).
continue;
That’s why nested L and M loops require not more than 2k iterations
}
overall.*/
suffix[u].pb(suff);
suff=max(suff,f[v]+w);
for (int s = 0; s <= k; s++) //s - length(size) of substring
}
for (int L = 0; L + s <= k; L++) { //L - left point
// Reversing is important
int R = L + s; //R - right point
REVERSE(suffix[u]);
if (s < 2) {
}
res[L][R] = 0; //DP base - nothing to break
11
FOR(i,0,sz)
1.12 LIS nlogk {
FOR(j,0,sz)
vector<int> d; {
int ans, n; FOR(k,0,sz)
{
int main() { m.mat[i][k]=(m.mat[i][k]+m1.mat
scanf("%d", &n); [i][j]*m2.mat[j][k])%mod;
for (int i = 0; i < n; i++) { }
int x; }
scanf("%d", &x); }
vector<int>::iterator it = lower_bound(d.begin(), d.end(), x); }
if (it == d.end()) d.push_back(x);
else *it = x; Matrix expo(Matrix &M, int n, int sz)
} {
printf("LIS = %d", d.size()); Matrix ret;
return 0; ret.init(sz);
}
if(n==0) return ret;
if(n==1) return M;
while(n!=0)
struct Matrix
{
{
if(n&1)
ll mat[MAX][MAX];
{
aux=ret;
Matrix(){}
matMult(ret,aux,P,sz);
}
// This initialization is important.
// Input matrix should be initialized separately
n>>=1;
13
2 Data Structures
aux=P; matMult(P,aux,aux,sz);
} 2.1 2D BIT
return ret;
} // Call with size of the grid
// Example: fenwick_tree_2d<int> Tree(n+1,m+1) for n x m grid indexed
from 1
} if (lx != rx) {
} int mx = (lx + rx) / 2;
void build_x(int vx, int lx, int rx) { if (x <= mx)
if (lx != rx) { update_x(vx*2, lx, mx, x, y, new_val);
int mx = (lx + rx) / 2; else
build_x(vx*2, lx, mx); update_x(vx*2+1, mx+1, rx, x, y, new_val);
build_x(vx*2+1, mx+1, rx); }
} update_y(vx, lx, rx, 1, 0, m-1, x, y, new_val);
build_y(vx, lx, rx, 1, 0, m-1); }
}
int sum_y(int vx, int vy, int tly, int try_, int ly, int ry) {
if (ly > ry)
return 0; 2.3 A DSU Problem
if (ly == tly && try_ == ry)
return t[vx][vy];
/* Problem: You are given a graph with edge-weights. Each node has some
int tmy = (tly + try_) / 2;
color.
return sum_y(vx, vy*2, tly, tmy, ly, min(ry, tmy))
Now you are also given some queries of the form (starting_node, weight).
+ sum_y(vx, vy*2+1, tmy+1, try_, max(ly, tmy+1), ry);
The
}
query means you can start from the starting_node and you can visit only
int sum_x(int vx, int tlx, int trx, int lx, int rx, int ly, int ry) {
those
if (lx > rx)
edges which have wight <= weight. You need to print the color which will
return 0;
occur
if (lx == tlx && trx == rx)
the maximum time in your journey. If two color occurs the same, output
return sum_y(vx, 1, 0, m-1, ly, ry);
the lower
int tmx = (tlx + trx) / 2;
indexed one.
return sum_x(vx*2, tlx, tmx, lx, min(rx, tmx), ly, ry)
Solution: idea is to use DSU small to large merging with binary-lifting.
+ sum_x(vx*2+1, tmx+1, trx, max(lx, tmx+1), rx, ly, ry);
*/
}
const int LOG = 17;
void update_y(int vx, int lx, int rx, int vy, int ly, int ry, int x, int
int n, m, a[MAX], parent[MAX], up[MAX][LOG], weight[MAX][LOG];
y, int new_val) {
// best (count,color_number) pair on a component after adding an edge
if (ly == ry) {
pii best[MAX];
if (lx == rx)
// (weight,color) pair which means you can get max-occurrence of ’color’
t[vx][vy] = new_val;
with ’weight’
else
vpii ans[MAX];
t[vx][vy] = t[vx*2][vy] + t[vx*2+1][vy];
// (color,cnt) pair for each component, stores all of them
} else {
set<pii> color[MAX];
int my = (ly + ry) / 2;
vector<array<int,3>> edges;
if (y <= my)
update_y(vx, lx, rx, vy*2, ly, my, x, y, new_val);
void clear()
else
{
update_y(vx, lx, rx, vy*2+1, my+1, ry, x, y, new_val);
// Initialize weights and 2^j parent of each node.
t[vx][vy] = t[vx][vy*2] + t[vx][vy*2+1];
// Initially, each node is 2^j-th parent of itself
}
FOR(i,1,n+1)
}
{
void update_x(int vx, int lx, int rx, int x, int y, int new_val) {
FOR(j,0,LOG)
15
} ll Tree[MAX+7][2];
int mid=(start+end)>>1;
struct Node update(left,start,mid,i,val);
{ update(right,mid+1,end,i,val);
ll bestSum, bestPrefix, bestSuffix, segSum; tree[node].merge(tree[left],tree[right]);
Node() }
{ Node query(int node, int start, int end, int i, int j)
bestSum=bestPrefix=bestSuffix=segSum=-INF; {
} if(i>end || j<start)
void merge(Node &l, Node &r) return Node();
{ if(start>=i && end<=j)
segSum=l.segSum+r.segSum; {
bestPrefix=max(l.bestPrefix,r.bestPrefix+l.segSum); return tree[node];
bestSuffix=max(r.bestSuffix,r.segSum+l.bestSuffix); }
bestSum=max(max(l.bestSum,r.bestSum),l.bestSuffix+r.bestPrefix); int left=node<<1;
} int right=left+1;
}tree[150005]; int mid=(start+end)>>1;
Node l=query(left,start,mid,i,j);
void init(int node, int start, int end) Node r=query(right,mid+1,end,i,j);
{ Node n;
if(start==end) n.merge(l,r);
{ return n;
tree[node].bestSum=tree[node].segSum=a[start]; }
tree[node].bestSuffix=tree[node].bestPrefix=a[start];
return;
}
int left=node<<1; 2.6 Binary Indexed Tree
int right=left+1;
int mid=(start+end)>>1;
init(left,start,mid); ll Tree[MAX];
init(right,mid+1,end); // This is equivalent to calculating lower_bound on prefix sums array
tree[node].merge(tree[left],tree[right]); // LOGN = log(N)
} int bit_search(int v)
void update(int node, int start, int end, int i, int val) {
{ int sum = 0;
if(i<start || i>end) int pos = 0;
return;
if(start>=i && end<=i) for(int i=LOGN; i>=0; i--)
{ {
tree[node].bestSum=tree[node].segSum=val; if(pos + (1 << i) < N and sum + Tree[pos + (1 << i)] < v)
tree[node].bestSuffix=tree[node].bestPrefix=val; {
a[start]=val; sum += Tree[pos + (1 << i)];
return; pos += (1 << i);
} }
int left=node<<1; }
int right=left+1; // +1 because ’pos’ will have position of largest value less than
’v’
18
{ {
if (v == p || done[v]) continue; calc(v, u, upto[v]);
dfs(v, u); }
sub[u] += sub[v]; }
} }
}
void clean(int u, int p, int val)
int getCentroid(int u, int p) {
{ cnt[val] = 0;
// cout<<u<<" "<<sub[u]<<endl;
for (auto v : graph[u]) for (auto v : graph[u])
{ {
if (!done[v] && v != p && sub[v] > total / 2) if (!done[v] && v != p)
return getCentroid(v, u); {
} clean(v, u, upto[v]);
}
return u; }
} }
void go(int u, int p, int val) void calcgcd(int u, int p, int val)
{ {
ans[val]++; upto[u] = val;
take[cent].insert(val);
cnt[val]++; for (auto v : graph[u])
{
for (auto v : graph[u]) if (!done[v] && v != p)
{ {
if (!done[v] && v != p) calcgcd(v, u, gcd(val, a[v]));
{ }
go(v, u, upto[v]); }
} }
}
} void solve(int u)
{
void calc(int u, int p, int val) total = 0;
{ dfs(u, -1);
for (auto it : take[cent])
{ cent = getCentroid(u, -1);
int g = gcd(val, it); calcgcd(cent, -1, a[cent]);
ans[g] += cnt[it];
} // debug("cent",cent);
done[cent] = true;
for (auto v : graph[u])
{ for (auto v : graph[cent])
if (!done[v] && v != p) {
20
int x = 1; }
while (true) return u;
{ }
if ((1 << (x + 1)) > Level[p]) break; void Decompose(int u, int p)
x++; {
} nodeCnt = 0;
FORr(i, x, 0) findSubgraph(u, u);
{ int Cent = findCentroid(u, u);
if (Level[p] - (1 << i) >= Level[q]) if (p == -1) p = Cent;
p = Table[p][i]; Parent[Cent] = p;
} itrALL(Graph[Cent], it)
if (p == q) return p; {
FORr(i, x, 0) int v = *it;
{ Graph[v].erase(Cent);
if (Table[p][i] != -1 && Table[p][i] != Table[q][i]) Decompose(v, Cent);
{ }
p = Table[p][i]; Graph[Cent].clear();
q = Table[q][i]; }
} void update(int u)
} {
return Table[p][0]; int x = u;
} while (true)
int Dist(int a, int b) {
{ Ans[x] = min(Ans[x], Dist(x, u));
return Level[a] + Level[b] - 2 * Level[findLCA(a, b)]; if (x == Parent[x]) break;
} x = Parent[x];
void findSubgraph(int u, int parent) }
{ }
Subgraph[u] = 1; int query(int u)
nodeCnt++; {
itrALL(Graph[u], it) int x = u;
{ int ret = INF;
int v = *it; while (true)
if (v == parent) continue; {
findSubgraph(v, u); ret = min(ret, Dist(u, x) + Ans[x]);
Subgraph[u] += Subgraph[v]; if (x == Parent[x]) break;
} x = Parent[x];
} }
int findCentroid(int u, int p) return ret;
{ }
itrALL(Graph[u], it) int main()
{ {
int v = *it; // ios_base::sync_with_stdio(0);
if (v == p) continue; // cin.tie(NULL); cout.tie(NULL);
if (Subgraph[v] > nodeCnt / 2) return findCentroid(v, u); // freopen("in.txt","r",stdin);
22
printf("%lld\n",ans); }
} else if (inNode[parent[u]][f] == mxCnt[parent[u]])
{
sum[parent[u]] += f;
return 0; }
} }
inNode[parent[v]].clear();
}
2.10 DSU on Tree Sample
void dfs(int u, int p)
{
/*
for (auto v : graph[u])
You are given a rooted tree with root in vertex 1. Each vertex is
{
coloured in some colour.
if (p == v) continue;
Let’s call colour c dominating in the subtree of vertex v if there are no
dfs(v, u);
other colours
merge(u, v);
that appear in the subtree of vertex v more times than colour c.
}
So it’s possible that two or more colours will be dominating in
the subtree of some vertex. The subtree of vertex v is the vertex v
out[u] = sum[parent[u]];
and all other vertices that contains vertex v in each path to the root.
}
For each vertex v find the sum of all dominating colours in the subtree
of vertex v.
int main()
*/
{
ios_base::sync_with_stdio(0);
int u, v, n, color[MAX], parent[MAX];
// cin.tie(NULL); cout.tie(NULL);
vi graph[MAX];
// freopen("in.txt","r",stdin);
map<int, int> inNode[MAX];
int mxCnt[MAX]; ll sum[MAX], out[MAX];
int test, cases = 1;
void merge(int u, int v)
n = getnum();
{
// ***Important: swapping parents
FOR(i, 1, n + 1)
if (inNode[parent[u]].size() < inNode[parent[v]].size())
{
swap(parent[u], parent[v]);
color[i] = getnum();
parent[i] = i;
for (auto it : inNode[parent[v]])
inNode[i][color[i]] = 1;
{
sum[i] = color[i];
int f = it.first, s = it.second;
mxCnt[i] = 1;
}
inNode[parent[u]][f] += s;
FOR(i, 1, n)
if (inNode[parent[u]][f] > mxCnt[parent[u]])
{
{
u = getnum();
mxCnt[parent[u]] = inNode[parent[u]][f];
v = getnum();
sum[parent[u]] = f;
24
{ while(chain[u]!=chain[v])
public: {
void init(int n) if(depth[head[chain[u]]]<depth[head[chain[v]]])
{ swap(u,v);
for(int i=0; i<=n; i++) nxt[i]=-1, chainsz[i]=0; int start=head[chain[u]];
cnt=pos=1; segtree.update(1,1,n,st[start],st[u],add);
} u=parent[start];
void dfs(int u, int p=-1, int d=0) }
{ if(depth[u]>depth[v]) swap(u,v);
parent[u]=p; segtree.update(1,1,n,st[u],st[v],add);
subsize[u]=1; }
depth[u]=d;
int query(int u, int v)
for(auto v: graph[u]) {
{ int ret=0;
if(v==p) continue; while(chain[u]!=chain[v])
dfs(v,u,d+1); {
subsize[u]+=subsize[v]; if(depth[head[chain[u]]]<depth[head[chain[v]]])
swap(u,v);
if(nxt[u]==-1 || subsize[v]>subsize[nxt[u]]) int start=head[chain[u]];
nxt[u]=v; // query on respective ds
} ret+=bit.query(st[start],st[u]);
} u=parent[start];
void decompose(int u, int p=-1) }
{
chain[u]=cnt-1; if(depth[u]>depth[v]) swap(u,v);
// May need to update in segment tree on pos with some ret+=bit.query(st[u],st[v]);
val[u]
st[u]=pos++; return ret;
// Take the node value to corresponding position }
// val[st[u]]=(ll)c[u]*a+b; } hld;
if(!chainsz[cnt-1]) head[cnt-1]=u;
chainsz[cnt-1]++;
if(nxt[u]!=-1) decompose(nxt[u],u); 2.18 How Many Values Less than a Given Value
for(auto v: graph[u])
// How many values in a range are less than or equal to the given value?
{
// The key idea is to sort the values under a node in the segment tree
if(v==p || v==nxt[u]) continue;
and use binary search to find
++cnt;
// the required count
decompose(v,u);
// Complexity is O(nlog^2n) for building
}
// The actual problem needed the number of such values and the cumulative
}
sum of them
void update(int u, int v, ll add)
// Tree[node].All has all the values and Tree[node].Pref has the prefix
{
sums
32
// Remember: upper_bound gives the number of values less than or equal to ret.first += right.first; ret.second += right.second;
given value in a sorted range return ret;
struct info }
{
vector<ll> All, Pref;
} Tree[MAX * 4];
ll T[MAX], Prefix[MAX]; 2.19 Li Chao Tree Lines
void build(int node, int l, int r)
{
typedef int ftype;
if (l == r)
typedef complex<ftype> point;
{
#define x real
Tree[node].All.pb(T[l]);
#define y imag
Tree[node].Pref.pb(T[l]);
return;
ftype dot(point a, point b) {
}
return (conj(a) * b).x();
int mid = (l + r) / 2;
}
build(lc, l, mid);
build(rc, mid + 1, r);
ftype f(point a, ftype x) {
for (auto it : Tree[lc].All)
return dot(a, {x, 1});
Tree[node].All.pb(it);
}
for (auto it : Tree[rc].All)
Tree[node].All.pb(it);
const int maxn = 2e5;
SORT(Tree[node].All);
ll now = 0;
point line[4 * maxn];
for (auto it : Tree[node].All)
{
void add_line(point nw, int v = 1, int l = 0, int r = maxn) {
Tree[node].Pref.pb(now + it);
int m = (l + r) / 2;
now += it;
bool lef = f(nw, l) < f(line[v], l);
}
bool mid = f(nw, m) < f(line[v], m);
}
if(mid) {
pair<ll, ll> query(int node, int l, int r, int x, int y, int val)
swap(line[v], nw);
{
}
if (x > r || y < l) return MP(0LL, 0LL);
if(r - l == 1) {
if (x <= l && r <= y)
return;
{
} else if(lef != mid) {
int idx = upper_bound(Tree[node].All.begin(),
add_line(nw, 2 * v, l, m);
Tree[node].All.end(), val) - Tree[node].All.begin();
} else {
if (idx > 0) return MP(Tree[node].Pref[idx - 1], idx);
add_line(nw, 2 * v + 1, m, r);
return MP(0LL, 0LL);
}
}
}
int mid = (l + r) / 2;
pair<ll, ll> ret, left, right;
int get(int x, int v = 1, int l = 0, int r = maxn) {
left = query(lc, l, mid, x, y, val);
int m = (l + r) / 2;
right = query(rc, mid + 1, r, x, y, val);
if(r - l == 1) {
ret.first += left.first; ret.second += left.second;
return f(line[v], x);
33
// New function is worse for l to mid, but this can be better return ret;
for right segment. }
if(fl>=0 && fm1>=0)
{ void calc(fun &fx)
update(rc,mid+1,r,x,y,fx); {
return; for(int i=0; i<offset; i++)
} {
aux[i]=min(aux[i],fx.eval(i));
// New function worse for mid+1 to r, but can be better for // prnt(fx.eval(i));
left segment }
if(fm2>=0 && fr>=0) }
{
update(lc,l,mid,x,y,fx); int main()
return; {
} // ios_base::sync_with_stdio(0);
// cin.tie(NULL); cout.tie(NULL);
// New function better for mid+1 to r, add it, old function // freopen("in.txt","r",stdin);
can still be better for left.
if(fm2<=0 && fr<=0) int test, cases = 1;
{
update(lc,l,mid,x,y,Tree[node]); scanf("%d", &test);
Tree[node]=fx;
return; int n;
}
} while(test--)
else if(l<r) {
{ scanf("%d", &n);
int mid=(l+r)/2;
init();
update(lc,l,mid,x,y,fx); int a, b, c, d;
update(rc,mid+1,r,x,y,fx);
} FOR(i,0,n)
} {
scanf("%d%d%d%d", &d, &c, &b, &a);
ll query(int node, int l, int r, int x) fun fx=fun(a,b,c,d);
{ calc(fx);
if(l==r) return Tree[node].eval(x); update(1,1,N,offset,N,fx);
}
int mid=(l+r)/2;
int q, x;
ll ret=Tree[node].eval(x); scanf("%d", &q);
ans-=cnt[a[idx]]*cnt[a[idx]]*a[idx];
cnt[a[idx]]++;
2.21 Mo Algorithm Example ans+=cnt[a[idx]]*cnt[a[idx]]*a[idx];
*/
struct info
}
{
int l, r, id;
inline void Remove(int idx)
info(){}
{
info(int l, int r, int id) : l(l), r(r), id(id){}
ans-=(2*cnt[a[idx]]-1)*a[idx];
};
cnt[a[idx]]--;
int n, t, a[2*MAX];
/* Actual meaning of the above code
info Q[2*MAX];
int Block, cnt[1000004];
ans-=cnt[a[idx]]*cnt[a[idx]]*a[idx];
ll ans=0;
cnt[a[idx]]--;
ll Ans[2*MAX];
ans+=cnt[a[idx]]*cnt[a[idx]]*a[idx];
// always constant
*/
// Farther improvement: When dividing the elements into blocks, we may
}
sort the first block in the
// ascending order of right borders, the second in descending, the third
int main()
in ascending order again, and so on.
{
// ios_base::sync_with_stdio(0);
// inline bool comp(const info &a, const info &b)
// cin.tie(NULL); cout.tie(NULL);
// {
// freopen("in.txt","r",stdin);
// if(a.l/blockSZ!=b.l/blockSZ)
// return a.l<b.l;
// Problem: For each query, find the value cnt[a[i]]*cnt[a[i]]*a[i]
// if((a.l/blockSZ)&1)
// return a.r<b.r;
scanf("%d%d", &n, &t);
// return a.r>b.r;
// }
Block=sqrt(n);
36
} ms(parent, -1);
} scanf("%d%d", &n, &m);
} blocSZ = sqrt(n);
int query(int p, int q) FOR(i, 1, n + 1)
{ {
if (dist[p] < dist[q]) swap(p, q); scanf("%d", &weight[i]);
int x = 1; }
while (true) FOR(i, 1, n)
{ {
if ((1 << (x + 1)) > dist[p]) break; scanf("%d%d", &u, &v);
x++; graph[u].pb(v);
} graph[v].pb(u);
FORr(i, x, 0) if (dist[p] - (1 << i) >= dist[q]) p = parent[p][i]; }
if (p == q) return p; dfs(1, 0, 0);
FORr(i, x, 0) sparse();
{ compress(n, weight, t);
if (parent[p][i] != -1 && parent[p][i] != parent[q][i]) (1, 1) << endl;
{ FOR(i, 1, 2 * n + 1) b[i] = t[aux[i]];
p = parent[p][i]; FOR(i, 0, m)
q = parent[q][i]; {
} scanf("%d%d", &u, &v);
} lca[i] = query(u, v);
return parent[p][0]; if (st[u] > st[v]) swap(u, v);
} if (lca[i] == u) Q.pb(info(st[u], st[v], i, 0));
int ans = 0; else Q.pb(info(en[u], st[v], i, 1));
void doit(int idx) }
{ sort(Q.begin(), Q.end(), [](const info & a, const info & b)->bool
if (!seen[aux[idx]]) {
{ if (a.u / blocSZ == b.u / blocSZ) return a.v < b.v;
cnt[b[idx]]++; return a.u < b.u;
if (cnt[b[idx]] == 1) ans++; });
} int L = 1, R = 0;
else FOR(i, 0, Q.size())
{ {
cnt[b[idx]]--; int l = Q[i].u, r = Q[i].v, anc = lca[Q[i].id];
if (cnt[b[idx]] == 0) ans--;
} while (R < r) { R++; doit(R); }
seen[aux[idx]] ^= 1; while (R > r) { doit(R); R--; }
} while (L > l) { L--; doit(L); }
int main() while (L < l) { doit(L); L++; }
{
// Each node has some weight associated with it if (Q[i].fl)
// u v : ask for how many different integers that represent the {
weight of if (!cnt[b[st[anc]]])
// nodes there are on the path from u to v. go[Q[i].id] = ans + 1;
38
/// 1-based index, returns the K’th element in the treap, -1 if none
#include <bits/stdtr1c++.h>
exists
#include <ext/pb_ds/assoc_container.hpp>
inline long long kth(int k){
#include <ext/pb_ds/tree_policy.hpp>
if (k < 1 || k > len) return -1;
using namespace std;
auto it = T.find_by_order(--k);
using namespace __gnu_pbds;
return ((*it) / ADD) - MAXVAL;
}
/*** Needs C++11 or C++14 ***/
/// Count of value < x in treap
/// Treap supporting duplicating values in set
inline int count(long long x){
/// Maximum value of treap * ADD must fit in long long
39
x += MAXVAL; Tree[node]=0;
int c = mp[--x]; }
return (T.order_of_key((x * ADD) + c));
} int update(int node, int l, int r, int pos, int val)
{
/// Number of elements in treap int x;
inline int size(){ x=++idx;
return len;
} if(l==r)
}; {
Tree[x]=val;
int main(){ return x;
} }
L[x]=L[node]; R[x]=R[node];
if(pos<=mid) L[x]=update(L[x],l,mid,pos,val);
// Calculate how many distinct values are there in a given range
else R[x]=update(R[x],mid+1,r,pos,val);
// Persistent Segment Tree implementation
// Actually used in Codeforces - The Bakery
Tree[x]=Tree[L[x]]+Tree[R[x]];
int n, k, a[MAX], last[MAX], nxt[MAX];
return x;
int idx=1;
}
int Tree[64*MAX], L[64*MAX], R[64*MAX], root[2*MAX], rt[MAX];
int pos[MAX];
int query(int node, int l, int r, int x, int y)
{
void build(int node, int l, int r)
if(x>r || y<l) return 0;
{
if(x<=l && r<=y) return Tree[node];
if(l==r)
{
int mid=(l+r)/2;
Tree[node]=0;
return;
int q1=query(L[node],l,mid,x,y);
}
int q2=query(R[node],mid+1,r,x,y);
L[node]=++idx;
return q1+q2;
R[node]=++idx;
}
// cout<<node<<" "<<L[node]<<" "<<R[node]<<endl;
int getCost(int l, int mid)
{
int mid=(l+r)/2;
return query(root[rt[mid]],1,n,l,mid);
}
build(L[node],l,mid);
build(R[node],mid+1,r);
int main()
40
{
if(l == r) return l; pnode last;
pnode version[N];
int mid = (l + r) >> 1;
if(nd->l->sum < k) return get_kth(k - nd->l->sum, mid + 1, r, void insert(int a, int time) {
nd->r); pnode v = version[time] = last = last->clone();
else return get_kth(k, l, mid, nd->l); for (int i = K - 1; i >= 0; --i) {
} int bit = (a >> i) & 1;
pnode &child = v->to[bit];
child = child->clone();
v = child;
2.27 Persistent Trie v->time = time;
}
}
#include <bits/stdc++.h>
int query(pnode v, int x, int l) {
using namespace std;
int ans = 0;
for (int i = K - 1; i >= 0; --i) {
// Problem: find maximum value (x^a[j]) in the range (l,r) where l<=j<=r
int bit = (x >> i) & 1;
if (v->to[bit]->go(l)) { // checking if this bit was inserted before
const int N = 1e5 + 100;
the range
const int K = 15;
ans |= 1 << i;
v = v->to[bit];
struct node_t;
} else {
typedef node_t * pnode;
v = v->to[bit ^ 1];
}
struct node_t {
}
int time;
return ans;
pnode to[2];
}
node_t() : time(0) {
to[0] = to[1] = 0;
void solve() {
}
int n, q;
bool go(int l) const {
scanf("%d %d", &n, &q);
if (!this) return false;
last = 0;
return time >= l;
for (int i = 0; i < n; ++i) {
}
int a;
pnode clone() {
scanf("%d", &a);
pnode cur = new node_t();
insert(a, i);
if (this) {
}
cur->time = time;
while (q--) {
cur->to[0] = to[0];
int x, l, r;
cur->to[1] = to[1];
scanf("%d %d %d", &x, &l, &r);
}
--l, --r;
return cur;
printf("%d\n", query(version[r], ~x, l));
}
// Trie version[r] contains the trie for [0...r] elements
};
42
} {
} tree[node] = a[l];
return;
}
if (l >= r) return;
2.28 RMQ Sparse Table int mid = (l + r) / 2;
build(node * 2, l, mid);
const int MAXN = (1 << 20); build(node * 2 + 1, mid + 1, r);
const int MAXLOG = 20; tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
struct sparse_table void upd(int node, int l, int r, int v)
{ {
int dp[MAXN][MAXLOG]; lazy[node] += v;
int prec_lg2[MAXN], n; tree[node] += (r - l + 1) * x;
}
sparse_table() { memset(dp, 0, sizeof(dp)); memset(prec_lg2, 0, void pushDown(int node, int l, int r) //passing update information to the
sizeof(prec_lg2)); n = 0; } children
{
void init(vector<int> &a) int mid = (l + r) / 2;
{ upd(node * 2, l, mid, lazy[node]);
n = a.size(); upd(node * 2 + 1, mid + 1, r, lazy[node]);
for(int i = 2; i < 2 * n; i++) prec_lg2[i] = prec_lg2[i >> lazy[node] = 0;
1] + 1; }
for(int i = 0; i < n; i++) dp[i][0] = a[i]; void update(int node, int l, int r, int x, int y, int v)
for(int j = 1; (1 << j) <= n; j++) {
for(int i = 0; i < n; i++) if (x > r || y < l) return;
dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j if (x >= l && r <= y)
- 1))][j - 1]); {
} upd(node, l, r, v);
return;
int query(int l, int r) }
{ pushDown(node, l, r);
int k = prec_lg2[r - l + 1]; int mid = (l + r) / 2;
return min(dp[l][k], dp[r - (1 << k) + 1][k]); update(node * 2, l, mid, x, y, v);
} update(node * 2 + 1, mid + 1, r, x, y, v);
}; tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
int main(){
int n, i, j, k, v, p, c, x, flag; 2.31 Segment Tree with Lazy Prop
while (scanf("%d", &n) != EOF){
// Maximum in a range with lazy propagation.
d = 0, vnow = 0;
class SegmentTree
while (n--){
{
scanf("%d", &flag);
public:
ll Tree[4*MAX], Lazy[4*MAX];
if (flag == 1){
void pushdown(int node)
scanf("%d %s", &p, str);
{
p -= d, vnow++;
if(Lazy[node])
R[vnow] = R[vnow - 1];
{
R[vnow].insert(p, str); /// Insert string str after
Lazy[lc]+=Lazy[node];
position p
Lazy[rc]+=Lazy[node];
}
Tree[lc]+=Lazy[node];
Tree[rc]+=Lazy[node];
if (flag == 2){
Lazy[node]=0;
scanf("%d %d", &p, &c);
}
p -= d, c -= d, vnow++;
}
R[vnow] = R[vnow - 1];
R[vnow].erase(p - 1, c); /// Remove c characters starting
void build(int node, int l, int r)
at position p
{
}
Lazy[node]=0;
if(l==r)
if (flag == 3){
{
scanf("%d %d %d", &v, &p, &c); /// Print c characters
Tree[node]=in[l]; // input values
starting at position p in version v
return;
}
v -= d, p -= d, c -= d;
int mid=(l+r)/2;
rope <char> sub = R[v].substr(p - 1, c); /// Get the
build(lc,l,mid);
substring of c characters from position p in version v
build(rc,mid+1,r);
for (auto it: sub){
Tree[node]=max(Tree[lc],Tree[rc]);
out[ye++] = it;
Lazy[node]=0;
44
}else{ select(p+1,root);
Node *y=x->pre,*z=y->pre; root->ch[1]->ch[0] = null;
if (z->ch[0]==y){ splay(root->ch[1],null);
if (y->ch[0]==x) rotate(y,1),rotate(x,1); }
else rotate(x,0),rotate(x,1); void split(int l,int r,Node*&s1)
}else{ {
if (y->ch[1]==x) rotate(y,0),rotate(x,0); Node* tmp=get(l,r);
else rotate(x,1),rotate(x,0); root->ch[1]->ch[0]=null;
} root->ch[1]->upd();
} root->upd();
} s1=tmp;
x->upd(); }
} void cut(int l,int r)
void select(int k,Node* f){ {
int tmp; Node* tmp;
Node* x=root; split(l,r,tmp);
x->pushdown(); select(root->size-2,null);
k++; root->ch[1]->ch[0]=tmp;
for(;;){ tmp->pre=root->ch[1];
x->pushdown(); root->ch[1]->upd();
tmp=x->ch[0]->size; root->upd();
if (k==tmp+1) break; }
if (k<=tmp) x=x->ch[0];
else{ void init(int n){
k-=tmp+1; clear();
x=x->ch[1]; root=newNode(0,null);
} root->ch[1]=newNode(n+1,root);
} root->ch[1]->ch[0]=build(1,n,root->ch[1]);
splay(x,f); splay(root->ch[1]->ch[0],null);
} }
root->ch[1]->upd();
root->upd(); return 0;
} }
T query(int l,int r)
{
Node *o = get(l,r);
return o->mx; 2.33 Venice Technique
}
/*
void addRange(int l,int r,T v)
We want a data structure capable of doing three main update-operations
{
and some
Node *o = get(l,r);
sort of query. The three modify operations are: add: Add an element to
o->add += v;
the set.
o->val += v;
remove: Remove an element from the set. updateAll: This one normally
o->sum += o->size * v;
changes in
splay(o,null);
this case subtract X from ALL the elements. For this technique it is
completely
}
required that the update is done to ALL the values in the set equally.
void output(int l,int r){
And also for this problem in particular we may need one query:
for (int i=l;i<=r;i++){
getMin: Give me the smallest number in the set.
select(i,null);
*/
cout<<root->val<<endl;
// Interface of the Data Structure
};
struct VeniceSet {
}
void add(int);
}St;
void remove(int);
void updateAll(int);
int getMin(); // custom for this problem
int size();
int main()
};
{
int n,m,a,b,c;
/*
Imagine you have an empty land and the government can make queries of the
scanf("%d%d", &n, &m);
following
type: * Make a building with A floors. * Remove a building with B floors.
for(int i= 1;i <= n;i ++ ) ar[i] = i;
* Remove
St.init(n);
C floors from all the buildings. (A lot of buildings can be vanished) *
Which is the
FOR(i,1,m+1)
smallest standing building. (Obviously buildings which are already
{
banished don’t count)
scanf("%d%d", &a, &b);
The operations 1,2 and 4 seems very easy with a set, but the 3 is very
St.cut(a,b);
cost effective
}
probably O(N) so you might need a lot of workers. But what if instead of
removing C
St.output(1,n);
floors we just fill the streets with enough water (as in venice) to cover
up the
48
first C floors of all the buildings :O. Well that seems like cheating but // get the negative number which we really did not
at least subtracted T[i]
those floor are now vanished :). So in order to do that we apart from the int toLow = mySet.getMin();
SET
we can maintain a global variable which is the water level. so in fact if // remove from total the amount we over counted
we total -= abs(toLow);
have an element and want to know the number of floors it has we can just
do // remove it from the set since I will never be able to
height - water_level and in fact after water level is for example 80, if substract from it again
we mySet.remove(toLow);
want to make a building of 3 floors we must make it of 83 floors so that }
it cout << total << endl;
can touch the land. }
*/ cout << endl;
struct VeniceSet {
multiset<int> S;
int water_level = 0;
void add(int v) {
S.insert(v + water_level); 3 Game
}
void remove(int v) { 3.1 Green Hacenbush
S.erase(S.find(v + water_level));
}
// Green Hackenbush
void updateAll(int v) {
vi graph[505];
water_level += v;
int go(int u, int p)
}
{
int getMin() {
int ret = 0;
return *S.begin() - water_level;
for (auto &v : graph[u])
}
{
int size() {
if (v == p) continue;
return S.size();
ret ^= (go(v, u) + 1);
}
}
};
return ret;
VeniceSet mySet;
}
for (int i = 0; i < N; ++i) {
int u, v, n;
mySet.add(V[i]);
int main()
mySet.updateAll(T[i]); // decrease all by T[i]
{
int total = T[i] * mySet.size(); // we subtracted T[i] from all
// ios_base::sync_with_stdio(0);
elements
// cin.tie(NULL); cout.tie(NULL);
// freopen("in.txt","r",stdin);
// in fact some elements were already less than T[i]. So we
int test, cases = 1;
probbaly are counting
cin >> test;
// more than what we really subtracted. So we look for all those
while (test--)
elements
{
while (mySet.getMin() < 0) {
cin >> n;
49
// Build upper hull typedef set<Points, bool(*)(const Points&, const Points&)> setType;
typedef setType::iterator setIT;
for(int i=n-2, t=k+1; i>=0; i--) setType s(&comp2);
{ double euclideanDistance(const Points &a, const Points &b)
while(Hull.size()>=t && {
cross(Hull[Hull.size()-2],Hull.back(),Points[i])<=0) // prnt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
{ return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
Hull.pop_back(); }
k--; map<double, map<double, int> > CNT;
} int main()
Hull.pb(Points[i]); {
k++; // ios_base::sync_with_stdio(0);
} // cin.tie(NULL); cout.tie(NULL);
// freopen("in.txt","r",stdin);
Hull.resize(k); while ((cin >> n) && n)
} {
FOR(i, 0, n) cin >> P[i].x >> P[i].y;
sort(P, P + n, comp1);
FOR(i, 0, n)
4.2 Counting Closest Pair of Points {
// printPoint(P[i]);
s.insert(P[i]);
int n;
CNT[P[i].x][P[i].y]++;
struct Points
}
{
// To check repeated points :/
double x, y;
// for(auto it: s) printPoint(it);
Points() {}
double ans = 10000;
Points(double x, double y) : x(x), y(y) { }
int idx = 0;
bool operator<(const Points &a) const
FOR(j, 0, n)
{
{
return x < a.x;
// cout<<"Point now: "; printPoint(P[j]);
}
if (CNT[P[j].x][P[j].y] > 1) ans = 0;
};
Points it = P[j];
bool comp1(const Points &a, const Points &b)
while (it.x - P[idx].x > ans)
{
{
return a.x < b.x;
s.erase(P[idx]);
}
idx++;
bool comp2(const Points &a, const Points &b)
}
{
Points low = Points(it.x, it.y - ans);
return a.y < b.y;
Points high = Points(it.x, it.y + ans);
}
setIT lowest = s.lower_bound(low);
void printPoint(Points a)
if (lowest != s.end())
{
{
cout << a.x << " " << a.y << endl;
setIT highest = s.upper_bound(high);
}
Points P[10005];
52
for (setIT now = lowest; now != highest; PT operator + (const PT &p) const { return PT(x+p.x, y+p.y); }
now++) PT operator - (const PT &p) const { return PT(x-p.x, y-p.y); }
{ PT operator * (double c) const { return PT(x*c, y*c ); }
double cur = sqrt(euclideanDistance PT operator / (double c) const { return PT(x/c, y/c ); }
(*now, it)); };
// prnt(cur);
if (cur == 0) continue; PT p[505];
// cout<<"Here:"<<endl; double dist[505][505];
// printPoint(*now); printPoint(it); prnt int n, m;
(cur);
if (cur < ans) void calcDist()
{ {
ans = cur; FOR(i,0,n)
} {
} FOR(j,i+1,n)
} dist[i][j]=dist[j][i]=sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)
s.insert(it); +(p[i].y-p[j].y)*(p[i].y-p[j].y));
} }
// cout<<"Set now:"<<endl; }
// for(auto I: s) printPoint(I);
if (ans < 10000) cout << setprecision(4) << fixed << ans // Returns maximum number of points enclosed by a circle of radius
<< endl; ’radius’
else prnt("INFINITY"); // where the circle is pivoted on point ’point’
s.clear(); // ’point’ is on the circumfurence of the circle
CNT.clear();
} int intelInside(int point, double radius)
return 0; {
} vector<pdb> ranges;
FOR(j,0,n)
{
4.3 Maximum Points to Enclose in a Circle of Given Radius if(j==point || dist[j][point]>2*radius) continue;
with Angular Sweep
double a1=atan2(p[point].y-p[j].y,p[point].x-p[j].x);
double a2=acos(dist[point][j]/(2*radius));
typedef pair<double,bool> pdb;
ranges.pb({a1-a2,START});
#define START 0
ranges.pb({a1+a2,END});
#define END 1
}
struct PT
sort(ALL(ranges));
{
double x, y;
int cnt=1, ret=cnt;
PT() {}
PT(double x, double y) : x(x), y(y) {}
for(auto it: ranges)
PT(const PT &p) : x(p.x), y(p.y) {}
53
{ The polygon must be such that every point on the circumference is visible
if(it.second) cnt--; from the first point in the vector.
else cnt++; It returns 0 for points outside, 1 for points on the circumference, and 2
ret=max(ret,cnt); for points inside.
} */
return ret; int insideHull2(const vector<PT> &H, int L, int R, const PT &p) {
} int len = R - L;
if (len == 2) {
// returns maximum amount of points enclosed by the circle of radius r int sa = sideOf(H[0], H[L], p);
// Complexity: O(n^2*log(n)) int sb = sideOf(H[L], H[L+1], p);
int sc = sideOf(H[L+1], H[0], p);
int go(double r) if (sa < 0 || sb < 0 || sc < 0) return 0;
{ if (sb==0 || (sa==0 && L == 1) || (sc == 0 && R ==
int cnt=0; (int)H.size()))
return 1;
FOR(i,0,n) return 2;
{ }
cnt=max(cnt,intelInside(i,r)); int mid = L + len / 2;
} if (sideOf(H[0], H[mid], p) >= 0)
return insideHull2(H, mid, R, p);
return cnt; return insideHull2(H, L, mid+1, p);
} }
}; m=take.size()-1;
ll solve() in.clear();
{
take.clear(); ms(Tree,0); ms(Lazy,0); FOR(i,0,n)
take.pb(-1); {
scanf("%d%d%d%d", &x, &y, &p, &q);
FOR(i,0,in.size())
{ in.pb(info(x,y,q,1));
take.pb(in[i].ymin); in.pb(info(p,y,q,-1));
take.pb(in[i].ymax); }
}
SORT(in);
SORT(take);
take.erase(unique(ALL(take)),take.end()); ll ans=solve();
55
adj[a].push_back(b);
printf("Case %d: %lld\n", cases++, ans); rev[b].push_back(a);
} }
// Useful when the graph only has weights 0 or 1. inline void add_and(int a, int b){
// Complexity becomes O(V+E) add_or(a, b);
add_or(a, -b);
for all v in vertices: add_or(-a, b);
dist[v] = inf }
dist[source] = 0;
deque d /// force variable x to be true (if x is negative, force !x to be
d.push_front(source) true)
while d.empty() == false: inline void force_true(int x){
vertex = get front element and pop_front if (x < 0) x = n - x;
// Go to all edges add_implication(neg(x), x);
for all edges e of form (vertex , u): }
// consider relaxing with 0 or 1 weight edges
if travelling e relaxes distance to u: /// force variable x to be false (if x is negative, force !x to be
relax dist[u] false)
if e.weight = 1: inline void force_false(int x){
d.push_back(u) if (x < 0) x = n - x;
else: add_implication(x, neg(x));
d.push_front(u) }
*/
struct tSAT{
5.2 2-SAT 2 int n, id[MAX][2];
vi G[MAX];
int ord, dis[MAX], low[MAX], sid[MAX], scc;
// for x or y add !x -> y, !y -> x
stack <int> s;
// x and y = (!x or y) and (x or !y) and (!x or !
/*
tSAT(int n): n(n){
inline void add_implication(int a, int b){
int now=0;
if (a < 0) a = n - a;
f(i,1,n+1){
if (b < 0) b = n - b;
f(j,0,2){
56
id[i][j]=++now; ++scc;
} while(1){
} int t=s.top();
} s.pop();
sid[t]=scc;
tSAT() {} if (t==u) break;
}
void add_edge(int u,int tu,int v,int tv){ }
G[id[u][tu]].pb(id[v][tv]); }
} }
bool feasible(){
scc=0; ord=0;
mem(dis,0); mem(sid,0); 5.3 2-SAT
f(i,1,2*n+1){
if(!dis[i]) tarjan(i);
const int N=20004;
}
int n, m, root=-1, leader[N], truths[N];
f(i,1,n+1){
vi graph[N], rev[N], order;
if(sid[id[i][0]]==sid[id[i][1]]) return false;
bool visited[N];
}
// clear() if necessary
return true;
void dfs_reverse(int u)
}
{
visited[u]=true;
vi solution(){
FOR(j,0,rev[u].size())
vi ans;
{
f(i,1,n+1){
int v=rev[u][j];
if(sid[id[i][0]]>sid[id[i][1]]) ans.pb(i);
if(!visited[v])
}
dfs_reverse(v);
return ans;
}
}
order.pb(u);
}
void tarjan(int u){
void dfs(int u)
s.push(u);
{
dis[u]=low[u]=++ord;
visited[u]=true;
f(i,0,G[u].size()){
leader[u]=root;
int v=G[u][i];
if (!dis[v]){
FOR(j,0,graph[u].size())
tarjan(v);
{
low[u]=min(low[v],low[u]);
int v=graph[u][j];
}
else if (!sid[v]){
if(!visited[v])
low[u]=min(dis[v],low[u]);
dfs(v);
}
}
}
}
if (low[u]==dis[u]){
void solve()
57
{ if(truths[leader[u]]==-1)
for(int i=2*m; i>=1; i--) {
{ truths[leader[u]]=true;
if(!visited[i]) truths[leader[u+m]]=false;
{ }
dfs_reverse(i); }
} }
} return true;
// important }
REVERSE(order); int main()
ms(visited,false); {
int test, cases = 1;
FOR(i,0,order.size()) scanf("%d", &test);
{ while(test--)
if(!visited[order[i]]) {
{ scanf("%d%d", &n, &m);
root=order[i];
dfs(order[i]); int u, v;
} ms(truths,-1);
}
} FOR(i,1,n+1)
{
bool sameSCC(int u, int v) scanf("%d%d", &u, &v);
{ // For each clause (u or v), we add to edges - (~u to v), (~v
return leader[u]==leader[v]; to u)
} if(u > 0)
bool assign() {
{ if(v > 0)
FOR(i,0,order.size()) {
{ graph[m+u].push_back(v); graph[m+v].push_back(u);
int u=order[i]; rev[v].push_back(m+u); rev[u].push_back(m+v);
} else {
if(u>m) graph[m+u].push_back(m-v); graph[-v].push_back(u);
{ rev[m-v].push_back(m+u); rev[u].push_back(-v);
if(sameSCC(u,u-m)) return false; }
if(truths[leader[u]]==-1) } else {
{ if(v > 0) {
truths[leader[u]]=true; graph[-u].push_back(v); graph[m+v].push_back(m-u);
truths[leader[u-m]]=false; rev[v].push_back(-u); rev[m-u].push_back(m+v);
} } else {
} graph[-u].push_back(m-v); graph[-v].push_back(m-u);
else rev[m-v].push_back(-u); rev[m-u].push_back(-v);
{ }
if(sameSCC(u,m+u)) return false; }
}
58
if (u==dfsroot)
solve(); rootchild++;
bool okay=assign(); articulate(v);
if (dfs_low[v]>=dfs_num[u])
if(okay) art_v[u]=true;
{ if (dfs_low[v]>dfs_num[u])
printf("Case %d: Yes\n", cases++); cout<<"Edge "<<u<<" & "<<v<<" is a
bridge."<<endl;
vi allow; dfs_low[u]=min(dfs_low[u],dfs_low[v]);
}
FOR(i,1,m+1) else if (v!=parent[u])
{ dfs_low[u]=min(dfs_low[u],dfs_num[v]);
if(truths[leader[i]]) }
{ }
allow.pb(i);
} int main()
} {
int n, m, u, v;
printf("%d", (int)allow.size()); cin>>n>>m;
FOR(i,0,allow.size()) cout<<" "<<allow[i]; for (int i=0; i<m; i++)
cout<<endl; {
} cin>>u>>v;
else printf("Case %d: No\n", cases++); graph[u].pb(v);
} graph[v].pb(u);
return 0; }
} cnt=0;
ms(dfs_num,-1);
for (int i=0; i<n; i++)
{
5.4 Articulation Points and Bridges if (dfs_num[i]==-1)
{
dfsroot=i;
vi graph[100];
rootchild=0;
int dfs_num[100], dfs_low[100], parent[100], cnt;
articulate(i);
int dfsroot, rootchild;
art_v[dfsroot]=(rootchild>1);
int art_v[100];
}
}
void articulate(int u)
prnt("Articulation points:");
{
for (int i=0; i<n; i++)
dfs_low[u]=dfs_num[u]=cnt++;
{
for (ul j=0; j<graph[u].size(); j++)
if (art_v[i])
{
cout<<"Vertex: "<<i<<endl;
int v=graph[u][j];
}
if (dfs_num[v]==-1)
return 0;
{
}
parent[v]=u;
59
5.5 BCC
void dfs(const ll& node, const ll& par) {
dfs_num[node] = low[node] = num++;
struct MagicComponents {
vis[node] = 1;
ll n_child = 0;
struct edge {
for (edge& e : adj[node]) {
ll u, v, id;
if (e.v == par) continue;
};
if (vis[e.v] == 0) {
++n_child;
ll num, n, edges;
e_stack.push_back(e);
dfs(e.v, node);
vector<ll> dfs_num, low, vis;
vector<ll> cuts; // art-vertices
low[node] = min(low[node], low[e.v]);
vector<edge> bridges; // bridge-edges
if (low[e.v] >= dfs_num[node]) {
vector<vector<edge>> adj; // graph
if (dfs_num[node] > 0 || n_child > 1)
vector<vector<edge>> bccs; // all the bccs where bcc[i] has all
cuts.push_back(node);
the edges inside it
if (low[e.v] > dfs_num[node]) {
deque<edge> e_stack;
bridges.push_back(e);
// Nodes are numberd from 0
pop(node);
} else pop(node);
MagicComponents(const ll& _n) : n(_n) {
}
adj.assign(n, vector<edge>());
} else if (vis[e.v] == 1) {
edges = 0;
low[node] = min(low[node], dfs_num[e.v]);
}
e_stack.push_back(e);
}
void add_edge(const ll& u, const ll& v) {
}
adj[u].push_back({u,v,edges});
vis[node] = 2;
adj[v].push_back({v,u,edges++});
}
}
void pop(const ll& u) {
void run(void) {
vector<edge> list;
vis.assign(n, 0);
for (;;) {
dfs_num.assign(n, 0);
edge e = e_stack.back();
low.assign(n, 0);
e_stack.pop_back();
bridges.clear();
list.push_back(e);
cuts.clear();
if (e.u == u) break;
bccs.clear();
}
e_stack = deque<edge>();
bccs.push_back(list);
num = 0;
}
for (ll i = 0; i < n; ++i) {
//# Make sure to call run before calling this function.
if (vis[i]) continue;
// Function returns a new graph such that all two connected
dfs(i, -1);
// components are compressed into one node and all bridges
}
// in the previous graph are the only edges connecting the
}
60
Finally, run dfs to find the level of each node and subtree size. int x=1;
Answer is the
(level of the lca of the nodes n[1]...n[k] + 1) and subtree size while(true)
of this ancestor {
*/ if((1<<(x+1))>L[p])
break;
vi graph[MAX], cost[MAX], dag[MAX], parent[MAX], Tree[MAX]; x++;
int u, v, t, n, m; }
int dist[MAX];
vector<int> all; FORr(i,x,0)
int L[MAX], table[MAX][18], sub[MAX]; {
bool visited[MAX]; if(L[p]-(1<<i) >= L[q])
p=table[p][i];
void clear() }
{
FOR(i,0,n) if(p==q) return p;
{
graph[i].clear(); FORr(i,x,0)
cost[i].clear(); {
dag[i].clear(); if(table[p][i]!=-1 && table[p][i]!=table[q][i])
parent[i].clear(); {
Tree[i].clear(); p=table[p][i];
sub[i]=0; q=table[q][i];
} }
all.clear(); }
ms(table,-1);
ms(visited,false); return table[p][0];
} }
while(!PQ.empty()) }
{
pii t=PQ.top(); all.pb(u);
PQ.pop(); }
FOR(j,0,dag[u].size()) FOR(i,0,m)
{ {
if(!visited[dag[u][j]]) topsort(dag[u][j]); scanf("%d%d%d", &u, &v, &t);
65
} }
for (int i = 0; i < ind; i++) return ans;
{ }
col[i] = -1; }
} int main()
for (int i = 0; i < ind; i++) {
{ vector <edge> e;
vis[i] = 0; int l, r, m;
} cin >> l >> r >> m;
for (int i = 0; i < x + y; i++) for (int i = 0; i < m; i++)
{ {
if (!g[i].empty()) int a, b;
{ cin >> a >> b;
dfs(i); a--, b--;
} e.push_back({a, b});
} }
vector <edge> to_l, to_r; auto ret = solve(e);
vector <int> cols; cout << *max_element(ret.begin(), ret.end()) + 1 << ’\n’;
for (int i = 0; i < (int) e.size(); i++) for (int c : ret)
{ {
cols.push_back(col[i]); cout << c + 1 << ’\n’;
if (col[i] == 0) }
{ }
to_l.push_back(e[i]);
}
else
{ 5.11 Edmonds Matching
to_r.push_back(e[i]);
}
/*
}
* Algorithm: Edmonds Blossom Maximum Matching in Generel Graph
auto x = solve(to_l);
* Order : O( N^4 )
auto y = solve(to_r);
* Note : vertx must be indexing based
int mx = *max_element(x.begin(), x.end()) + 1;
*/
int p_x = 0, p_y = 0;
vector <int> ans;
#include<stdio.h>
for (int i = 0; i < (int) e.size(); i++)
#include<string.h>
{
using namespace std;
if (cols[i] == 0)
#define MAX_V 103
{
#define MAX_E MAX_V*MAX_V
ans.push_back(x[p_x++]);
}
long nV,nE,Match[MAX_V];
else
long Last[MAX_V], Next[MAX_E], To[MAX_E];
{
long eI;
ans.push_back(mx + y[p_y++]);
long q[MAX_V], Pre[MAX_V], Base[MAX_V];
}
bool Hash[MAX_V], Blossom[MAX_V], Path[MAX_V];
68
}
int main( void ){ }
eI = 0; if (n > m) m = n;
memset( Last,-1,sizeof(Last));
ll i, j, a, b, c, d, r, w;
} for (i = 1; i <= n; i++){
P[0] = i, b = 0;
for (j = 0; j <= m; j++) minv[j] = inf, visited[j] = false;
of V into two non-empty sets A and B. Earlier, when we looked at network used[last] = true;
flows, we worked with the closely related definition of an s-t cut: cut.push_back(last);
there, given if (best_weight == -1 || w[last] < best_weight) {
a directed graph G = (V, E) with distinguished source and sink nodes s best_cut = cut;
and t, best_weight = w[last];
an s-t cut was defined to be a partition of V into sets A and B such that }
s A } else {
and t B. Our definition now is slightly different, since the for (ll j = 0; j < N; j++)
underlying graph w[j] += weights[last][j];
is now undirected and there is no source or sink. added[last] = true;
This problem can be solved by max-flow. First we remove undirected edges }
and replace }
them by two opposite directed edge. Now we fix a node s. Then we consider }
each of return make_pair(best_weight, best_cut);
the n nodes as t and run max-flow. The minimum of those values is the }
answer. };
This is O(n^3).
*/ int main() {
ll T;
struct Stoer_Wagner{ sl(T);
vector <vl> weights; f(t,1,T+1){
Stoer_Wagner(ll N){ ll N,M;
weights.resize(N,vl(N,0)); sll(N,M);
} Stoer_Wagner SW(N);
void AddEdge(ll from, ll to, ll cap){ f(i,0,M){
weights[from][to]+=cap; ll a,b,c;
weights[to][from]+=cap; slll(a,b,c);
} SW.AddEdge(a-1,b-1,c);
pair<ll, vl> GetMinCut() { }
ll N = weights.size(); pf("Case #%lld: ",t); pfl(SW.GetMinCut().x);
vl used(N), cut, best_cut; }
ll best_weight = -1; }
}
T matching() { // maximum weight matching
printf("%d\n", hopcroft_karp()); fill(lx + 1, lx + 1 + n, numeric_limits<T>::lowest());
ms(ly,0);
return 0; ms(match,0);
} for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) lx[i] = max(lx[i], g[i][j]);
}
for (int k = 1; k <= n; ++k) {
5.15 Hungarian Weighted Matching fill(slack + 1, slack + 1 + m, numeric_limits<T>::max());
while (true) {
ms(vx,0);
// hungarian weighted matching algo
ms(vy,0);
// finds the max cost of max matching, to find mincost, add edges as
if (find(k)) break;
negatives
else {
// Nodes are indexed from 1 on both sides
T delta = numeric_limits<T>::max();
template<typename T>
for (int i = 1; i <= m; ++i) {
struct KuhnMunkras { // n for left, m for right
if (!vy[i]) delta = min(delta, slack[i]);
int n, m, match[maxM];
}
T g[maxN][maxM], lx[maxN], ly[maxM], slack[maxM];
for (int i = 1; i <= n; ++i) {
bool vx[maxN], vy[maxM];
if (vx[i]) lx[i] -= delta;
}
void init(int n_, int m_) {
for (int i = 1; i <= m; ++i) {
ms(g,0); n = n_, m = m_;
if (vy[i]) ly[i] += delta;
}
if (!vy[i]) slack[i] -= delta;
}
void add(int u, int v, T w) {
}
g[u][v] = w;
}
}
}
T result = 0;
bool find(int x) {
for (int i = 1; i <= n; ++i) result += lx[i];
vx[x] = true;
for (int i = 1; i <= m; ++i) result += ly[i];
for (int y = 1; y <= m; ++y) {
return result;
if (!vy[y]) {
}
T delta = lx[x] + ly[y] - g[x][y];
};
if (delta==0) {
vy[y] = true;
if (match[y] == 0 || find(match[y])) {
match[y] = x;
return true;
5.16 Johnson’s Algorithm
}
} else slack[y] = min(slack[y], delta); /// Johnson’s algorithm for all pair shortest paths in sparse graphs
} /// Complexity: O(N * M) + O(N * M * log(N))
}
return false; const long long INF = (1LL << 60) - 666;
}
73
5.19 LCA }
}
vi graph[100];
return P[p];
int P[100], L[100], table[100][20];
}
void dfs(int from, int to, int depth)
{
void build(int n)
P[to]=from;
{
L[to]=depth;
ms(table,-1);
FOR(i,0,(int)graph[to].size())
{
FOR(i,0,n)
int v=graph[to][i];
table[i][0]=P[i];
if(v==from)
continue;
for(int j=1; 1<<j < n; j++)
dfs(to,v,depth+1);
{
}
for(int i=0; i<n; i++)
}
{
if(table[i][j-1]!=-1)
int query(int n, int p, int q)
table[i][j]=table[table[i][j-1]][j-1];
{
}
if(L[p]<L[q]) swap(p,q);
}
}
int x=1;
while(true)
{
if((1<<(x+1))>L[p])
5.20 Manhattan MST
break;
x++; int n;
} vi graph[MAX], cost[MAX];
if (e.capacity > e.flow && level[u] < bound R, replace the edge with capacity R-L.
level[e.dst]) { Let, sum[u] = (sum of lowerbounds of ingoing edges to u) - (sum of
flow_type f = augment(e.dst, min(cur, lowerbounds of
e.capacity - e.flow)); outgoing edges from u),
if (f > 0) { here u can be all nodes of the graph, including s and t. For all such u,
e.flow += f; if sum[u]>0
r.flow -= f; add edge (s’,u,sum[u]), add sum[u] to a value ’total’, otherwise add edge
return f; (u,t’,-sum[u]).
} Lastly add (t,s,INF). Then run max-flow from s’ to t’.
} A feasible flow won’t exist if flow from s’ to t’ < total, otherwise
} if we run a maxflow from s to t (not s’ to t’), we get the max-flow
return flow_type(0); satisfying the bounds.
}; ***
for (int u = 0; u < n; ++u) // initialize To find the minimal flow satisfying the bounds, we do a binary search on
for (auto &e : adj[u]) e.flow = 0; the
capacity of the edge (t,s,INF). Each time during binary search, we check
flow_type flow = 0; if a feasible
while (levelize() >= 0) { flow exists or not with current capacity of (t,s,INF) edge.
fill(all(iter), 0); */
for (flow_type f; (f = augment(s, INF)) > 0; )
flow += f; struct Edge
} {
return flow; int to, rev, f, cap;
} };
};
}
} for(int &i=work[u]; i<(int)graph[u].size(); i++)
{
void addEdge(int s, int t, int cap) Edge &e=graph[u][i];
{
Edge a={t,(int)graph[t].size(),0,cap}; if(e.cap<=e.f) continue;
Edge b={s,(int)graph[s].size(),0,0};
int v=e.to;
// If our graph has bidirectional edges
// Capacity for the Edge b will equal to cap if(dist[v]==dist[u]+1)
// For directed, it is 0 {
int df=dfs(v,min(f,e.cap-e.f));
graph[s].emplace_back(a);
graph[t].emplace_back(b); if(df>0)
} {
e.f+=df;
bool bfs() graph[v][e.rev].f-=df;
{
ms(dist,-1); return df;
dist[src]=0; }
int qt=0; }
q[qt++]=src; }
vector<vector<edge>> adj;
//
graph(int n) : n(n), adj(n) { }
// Maximum Flow (Edmonds-Karp)
void add_edge(int src, int dst, int capacity) {
//
adj[src].push_back({src, dst, capacity, 0,
// Description:
adj[dst].size()});
// Given a directed network G = (V, E) with edge capacity c: E->R.
adj[dst].push_back({dst, src, 0, 0, adj[src].size() - 1});
// The algorithm finds a maximum flow.
}
//
int max_flow(int s, int t) {
// Algorithm:
for (int u = 0; u < n; ++u)
// Edmonds-Karp shortest augmenting path algorithm.
for (auto &e : adj[u]) e.residue = e.capacity;
//
int total = 0;
// Complexity:
while (1) {
// O(n m^2)
vector<int> prev(n, -1); prev[s] = -2;
//
queue<int> que; que.push(s);
// Verified:
while (!que.empty() && prev[t] == -1) {
// AOJ GRL_6_A: Maximum Flow
int u = que.front(); que.pop();
//
for (edge &e : adj[u]) {
// Reference:
if (prev[e.dst] == -1 && e.residue >
// B. H. Korte and J. Vygen (2008):
0) {
// Combinatorial Optimization: Theory and Algorithms.
prev[e.dst] = e.rev;
// Springer Berlin Heidelberg.
que.push(e.dst);
//
}
}
#include <iostream>
}
#include <vector>
if (prev[t] == -1) break;
#include <queue>
int inc = INF;
#include <cstdio>
for (int u = t; u != s; u = adj[u][prev[u]].dst)
#include <algorithm>
inc = min(inc, rev(adj[u][prev[u]]).residue);
#include <functional>
for (int u = t; u != s; u = adj[u][prev[u]].dst) {
adj[u][prev[u]].residue += inc;
using namespace std;
rev(adj[u][prev[u]]).residue -= inc;
}
#define fst first
total += inc;
#define snd second
} // { u : visited[u] == true } is s-side
#define all(c) ((c).begin()), ((c).end())
return total;
}
const int INF = 1 << 30;
};
struct graph {
int n;
int main() {
struct edge {
for (int n, m; scanf("%d %d", &n, &m) == 2; ) {
int src, dst;
graph g(n);
int capacity, residue;
for (int i = 0; i < m; ++i) {
size_t rev;
int u, v, w;
};
81
scanf("%d %d %d", &u, &v, &w); const int INF = 1 << 30;
g.add_edge(u, v, w); struct graph {
} typedef long long flow_type;
printf("%d\n", g.max_flow(0, n - 1)); struct edge {
} int src, dst;
} flow_type capacity, flow;
size_t rev;
};
int n;
5.24 Max Flow Ford Fulkerson vector<vector<edge>> adj;
graph(int n) : n(n), adj(n) { }
void add_edge(int src, int dst, flow_type capacity) {
//
adj[src].push_back({src, dst, capacity, 0,
// Ford-Fulkerson’s maximum flow
adj[dst].size()});
//
adj[dst].push_back({dst, src, 0, 0, adj[src].size() - 1});
// Description:
}
// Given a directed network G = (V, E) with edge capacity c: E->R.
int max_flow(int s, int t) {
// The algorithm finds a maximum flow.
vector<bool> visited(n);
//
function<flow_type(int, flow_type)> augment = [&](int u,
// Algorithm:
flow_type cur) {
// Ford-Fulkerson’s augmenting path algorithm
if (u == t) return cur;
//
visited[u] = true;
// Complexity:
for (auto &e : adj[u]) {
// O(m F), where F is the maximum flow value.
if (!visited[e.dst] && e.capacity > e.flow) {
//
flow_type f = augment(e.dst,
// Verified:
min(e.capacity - e.flow, cur));
// AOJ GRL_6_A: Maximum Flow
if (f > 0) {
//
e.flow += f;
// Reference:
adj[e.dst][e.rev].flow -= f;
// B. H. Korte and J. Vygen (2008):
return f;
// Combinatorial Optimization: Theory and Algorithms.
}
// Springer Berlin Heidelberg.
}
//
}
return flow_type(0);
#include <iostream>
};
#include <vector>
for (int u = 0; u < n; ++u)
#include <cstdio>
for (auto &e : adj[u]) e.flow = 0;
#include <algorithm>
#include <functional>
flow_type flow = 0;
while (1) {
using namespace std;
fill(all(visited), false);
flow_type f = augment(s, INF);
#define fst first
if (f == 0) break;
#define snd second
flow += f;
#define all(c) ((c).begin()), ((c).end())
}
82
parent[v] = eIdx;
int cap[MAX], flow[MAX], cost[MAX], dis[MAX];
if(!inqueue[v]){ int n, m, s, t, Q[10000010], adj[MAX], link[MAX], last[MAX],
q.push(v); from[MAX], visited[MAX];
queuetime[v]++;
inqueue[v] = true; void init(int nodes, int source, int sink){
m = 0, n = nodes, s = source, t = sink;
if(queuetime[v] == n+2){ for (int i = 0; i <= n; i++) last[i] = -1;
negativecycle = true; }
break;
} void addEdge(int u, int v, int c, int w){
} adj[m] = v, cap[m] = c, flow[m] = 0, cost[m] = +w, link[m] =
} last[u], last[u] = m++;
} adj[m] = u, cap[m] = 0, flow[m] = 0, cost[m] = -w, link[m] =
} last[v], last[v] = m++;
}
return dist[t] != (1LL<<62);
} bool spfa(){
int i, j, x, f = 0, l = 0;
long long sendFlow(int v, long long curFlow){ for (i = 0; i <= n; i++) visited[i] = 0, dis[i] = INF;
if(parent[v] == -1)
return curFlow; dis[s] = 0, Q[l++] = s;
int eIdx = parent[v]; while (f < l){
int u = e[eIdx].u; ll w = e[eIdx].cost; i = Q[f++];
for (j = last[i]; j != -1; j = link[j]){
long long f = sendFlow(u, min(curFlow, e[eIdx].cap)); if (flow[j] < cap[j]){
x = adj[j];
cost += f*w; if (dis[x] > dis[i] + cost[j]){
e[eIdx].cap -= f; dis[x] = dis[i] + cost[j], from[x] = j;
e[eIdx^1].cap += f; if (!visited[x]){
visited[x] = 1;
return f; if (f && rand() & 7) Q[--f] = x;
} else Q[l++] = x;
}; }
}
}
}
5.31 Min Cost Max Flow 3 visited[i] = 0;
}
return (dis[t] != INF);
// This gave AC for CF 813D Two Melodies but the other one was TLE
}
// By sgtlaugh
// we can return all the flow values for each edge from this function
// flow[i] contains the amount of flow in i-th edge
// vi solve()
namespace mcmf{
pair <int, int> solve(){
const int MAX = 1000010;
int i, j;
const int INF = 1 << 25;
90
int mincost = 0, maxflow = 0; void addB(Index i, Index j, Flow capacity = InfCapacity, Cost cost
= Cost()) {
while (spfa()){ add(i, j, capacity, cost);
int aug = INF; add(j, i, capacity, cost);
for (i = t, j = from[i]; i != s; i = adj[j ^ 1], j = from[i]){ }
aug = min(aug, cap[j] - flow[j]); pair<Cost, Flow> minimumCostMaximumFlow(Index s, Index t, Flow f =
} InfCapacity,
for (i = t, j = from[i]; i != s; i = adj[j ^ 1], j = from[i]){ bool bellmanFord = false) {
flow[j] += aug, flow[j ^ 1] -= aug; int n = g.size();
} vector<Cost> dist(n); vector<Index> prev(n); vector<Index>
maxflow += aug, mincost += aug * dis[t]; prevEdge(n);
} pair<Cost, Flow> total = make_pair(0, 0);
// edges are indexed from 0 to m vector<Cost> potential(n);
// vi ret(flow,flow+m) while (f > 0) {
// to find flow of a specific edge, we just noticed that flow[2*i] fill(dist.begin(), dist.end(), InfCost);
contains if (bellmanFord || total.second == 0) {
// the flow amount in i-th edge dist[s] = 0;
return make_pair(mincost, maxflow); for (int k = 0; k < n; k++) {
} bool update = false;
} for (int i = 0; i < n; i++)
if (dist[i] != InfCost)
for (Index ei = 0; ei
<
(Index)g[i].size();
5.32 Min Cost Max Flow with Bellman Ford ei ++) {
const Edge &e =
g[i][ei];
const int InfCost = 1e9;
if (e.capacity
<= 0)
struct MinimumCostMaximumFlow {
continue;
typedef int Index; typedef int Flow; typedef int Cost;
Index j = e.to;
static const Flow InfCapacity = 1e9;
Cost d =
struct Edge {
dist[i] +
Index to; Index rev;
e.cost;
Flow capacity; Cost cost;
if (dist[j] > d
};
) {
vector<vector<Edge> > g;
dist[j]
void init(Index n) { g.assign(n, vector<Edge>()); }
= d;
void add(Index i, Index j, Flow capacity = InfCapacity, Cost cost
prev[j]
= Cost()) {
= i;
Edge e, f; e.to = j, f.to = i; e.capacity = capacity,
prevEdge[j]
f.capacity = 0; e.cost = cost, f.cost = -cost;
= ei;
g[i].push_back(e); g[j].push_back(f);
update =
g[i].back().rev = (Index)g[j].size() - 1; g[j].back().rev
true;
= (Index)g[i].size() - 1;
}
}
91
} }
if (!update) break; }
} return total;
} else { }
vector<bool> vis(n); } network;
priority_queue<pair<Cost, Index> > q;
q.push(make_pair(-0, s)); dist[s] = 0;
while (!q.empty()) {
Index i = q.top().second; q.pop(); 5.33 Minimum Path Cover in DAG
if (vis[i]) continue;
vis[i] = true;
#include <bits/stdtr1c++.h>
for (Index ei = 0; ei <
(Index)g[i].size(); ei ++) {
#define MAX 505
const Edge &e = g[i][ei];
#define clr(ar) memset(ar, 0, sizeof(ar))
if (e.capacity <= 0) continue;
#define read() freopen("lol.txt", "r", stdin)
Index j = e.to; Cost d =
#define dbg(x) cout << #x << " = " << x << endl
dist[i] + e.cost +
#define ran(a, b) ((((rand() << 15) ^ rand()) % ((b) - (a) + 1)) + (a))
potential[i] -
potential[j];
using namespace std;
if (d < dist[i]) d = dist[i];
/// Minimum path cover/Maximum independent set in DAG
if (dist[j] > d) {
namespace dag{
dist[j] = d; prev[j] =
/// For transitive closure and minimum path cover with not
i; prevEdge[j] =
necessarily disjoint vertex
ei;
bool ar[MAX][MAX];
q.push(make_pair(-d,
j));
vector <int> adj[MAX];
}
bool visited[MAX], first_set[MAX], second_set[MAX];
}
int n, L[MAX], R[MAX], D[MAX], Q[MAX], dis[MAX], parent[MAX];
}
}
inline void init(int nodes){ /// Number of vertices in DAG
if (dist[t] == InfCost) break;
n = nodes;
if (!bellmanFord) for (Index i = 0; i < n; i ++)
for (int i = 0; i < MAX; i++) adj[i].clear();
potential[i] += dist[i];
}
Flow d = f; Cost distt = 0;
for (Index v = t; v != s; ) {
inline void add_edge(int u, int v){ /// 0 based index, directed edge
Index u = prev[v]; const Edge &e =
of DAG
g[u][prevEdge[v]];
adj[u].push_back(v);
d = min(d, e.capacity); distt += e.cost; v =
}
u;
}
bool dfs(int i){
f -= d; total.first += d * distt; total.second += d;
int len = adj[i].size();
for (Index v = t; v != s; v = prev[v]) {
for (int j = 0; j < len; j++){
Edge &e = g[prev[v]][prevEdge[v]];
int x = adj[i][j];
e.capacity -= d; g[e.to][e.rev].capacity +=
if (L[x] == -1 || (parent[L[x]] == i)){
d;
if (L[x] == -1 || dfs(L[x])){
92
L[x] = i, R[i] = x; }
return true; }
}
} void transitive_closure(){ /// Transitive closure in O(n * m)
} clr(ar);
return false; int i, j, k, l;
} for (i = 0; i < n; i++){
l = adj[i].size();
bool bfs(){ for (j = 0; j < l; j++){
clr(visited); ar[i][adj[i][j]] = true;
int i, j, x, d, f = 0, l = 0; }
adj[i].clear();
for (i = 0; i < n; i++){ }
if (R[i] == -1){
visited[i] = true; for (k = 0; k < n; k++){
Q[l++] = i, dis[i] = 0; for (i = 0; i < n; i++){
} if (ar[i][k]){
} for (j = 0; j < n; j++){
if (ar[k][j]) ar[i][j] = true;
while (f < l){ }
i = Q[f++]; }
int len = adj[i].size(); }
for (j = 0; j < len; j++){ }
x = adj[i][j], d = L[x];
if (d == -1) return true; for (i = 0; i < n; i++){
for (j = 0; j < n; j++){
else if (!visited[d]){ if (i != j && ar[i][j]){
Q[l++] = d; adj[i].push_back(j);
parent[d] = i, visited[d] = true, dis[d] = dis[i] + 1; }
} }
} }
} }
return false; /// Minimum vertex disjoint path cover in DAG. Handle isolated
} vertices appropriately
int minimum_disjoint_path_cover() {
void get_path(int i){ int i, res = 0;
first_set[i] = true; memset(L, -1, sizeof(L));
int j, x, len = adj[i].size(); memset(R, -1, sizeof(R));
return n - res; }
} }
FOR(j,1,n+1) Output:
{ - maximum flow value
// cout<<d[j]<<endl;
if(d[j]!=INF) Todo:
ret+=d[j]; - implement Phase II (flow network from preflow network)
} - implement GetMinCut()
return ret; */
}
// To obtain the actual flow values, look at all edges with capacity > 0
int main() // Zero capacity edges are residual edges
{
int a, b, c; template <class T> struct Edge {
scanf("%d%d", &n, &m); int from, to, index;
FOR(i,0,m) T cap, flow;
{
scanf("%d%d%d", &a, &b, &c); Edge(int from, int to, T cap, T flow, int index): from(from), to(to),
graph[a].pb(b); cap(cap), flow(flow), index(index) {}
graph[b].pb(a); };
cost[a].pb(c);
cost[b].pb(c); template <class T> struct PushRelabel {
} int n;
cout<<Prim()<<endl; vector <vector <Edge <T>>> adj;
vector <T> excess;
return 0; vector <int> dist, count;
} vector <bool> active;
vector <vector <int>> B;
int b;
queue <int> Q;
5.35 Push Relabel 2
PushRelabel (int n): n(n), adj(n) {}
/*
void AddEdge (int from, int to, int cap) {
Implementation of highest-label push-relabel maximum flow
adj[from].push_back(Edge <T>(from, to, cap, 0, adj[to].size()));
with gap relabeling heuristic.
if (from == to) {
adj[from].back().index++;
Running time:
}
O(|V|^2|E|^{1/2})
adj[to].push_back(Edge <T>(to, from, 0, 0, adj[from].size() - 1));
Usage:
}
- add edges by AddEdge()
- GetMaxFlow(s, t) returns the maximum flow from s to t
void Enqueue (int v) {
if (!active[v] && excess[v] > 0 && dist[v] < n) {
Input:
active[v] = true;
- graph, constructed using AddEdge()
B[dist[v]].push_back(v);
- (s, t), (source, sink)
b = max(b, dist[v]);
95
} } else {
} Relabel(v);
}
void Push (Edge <T> &e) { }
T amt = min(excess[e.from], e.cap - e.flow); }
if (dist[e.from] == dist[e.to] + 1 && amt > T(0)) {
e.flow += amt; T GetMaxFlow (int s, int t) {
adj[e.to][e.index].flow -= amt; dist = vector <int>(n, 0), excess = vector<T>(n, 0), count =
excess[e.to] += amt; vector <int>(n + 1, 0), active = vector <bool>(n, false), B =
excess[e.from] -= amt; vector <vector <int>>(n), b = 0;
Enqueue(e.to);
} for (auto &e: adj[s]) {
} excess[s] += e.cap;
}
void Gap (int k) {
for (int v = 0; v < n; v++) if (dist[v] >= k) { count[0] = n;
count[dist[v]]--; Enqueue(s);
dist[v] = max(dist[v], n); active[t] = true;
count[dist[v]]++;
Enqueue(v); while (b >= 0) {
} if (!B[b].empty()) {
} int v = B[b].back();
B[b].pop_back();
void Relabel (int v) { active[v] = false;
count[dist[v]]--; Discharge(v);
dist[v] = n; } else {
for (auto e: adj[v]) if (e.cap - e.flow > 0) { b--;
dist[v] = min(dist[v], dist[e.to] + 1); }
} }
count[dist[v]]++; return excess[t];
Enqueue(v); }
}
T GetMinCut (int s, int t, vector <int> &cut);
void Discharge(int v) { };
for (auto &e: adj[v]) {
if (excess[v] > 0) {
Push(e);
} else { 5.36 Push Relabel
break;
}
#define sz(x) (int)(x).size()
}
struct Edge {
if (excess[v] > 0) {
int v;
if (count[dist[v]] == 1) {
ll flow, C;
Gap(dist[v]);
int rev;
96
}; count[dist[v]] ++;
enqueue(v);
template <int SZ> struct PushRelabel { }
vector<Edge> adj[SZ];
ll excess[SZ]; void discharge(int v) {
int dist[SZ], count[SZ+1], b = 0; for (auto &e: adj[v]) {
bool active[SZ]; if (excess[v] > 0) push(v,e);
vi B[SZ]; else break;
}
void addEdge(int u, int v, ll C) { if (excess[v] > 0) {
Edge a{v, 0, C, sz(adj[v])}; if (count[dist[v]] == 1) gap(dist[v]);
Edge b{u, 0, 0, sz(adj[u])}; else relabel(v);
adj[u].pb(a), adj[v].pb(b); }
} }
//
// Algorithm: vector<vector<int>> strongly_connected_components() { // kosaraju
// Kosaraju’s algorithm performs DFS on G and rev(G). vector<int> ord, visited(n);
// First DFS finds topological ordering of SCCs, and vector<vector<int>> scc;
// the second DFS extracts components. function<void(int, vector<vector<int>>&, vector<int>&)> dfs
// = [&](int u, vector<vector<int>> &adj, vector<int> &out) {
// Complexity: visited[u] = true;
// O(n + m) for (int v : adj[u])
// if (!visited[v]) dfs(v, adj, out);
// Verified: out.push_back(u);
// SPOJ 6818 };
// for (int u = 0; u < n; ++u)
// References: if (!visited[u]) dfs(u, adj, ord);
// A. V. Aho, J. E. Hopcroft, and J. D. Ullman (1983): fill(all(visited), false);
// Data Structures and Algorithms, for (int i = n - 1; i >= 0; --i)
// Addison-Wesley. if (!visited[ord[i]])
// scc.push_back({}), dfs(ord[i], rdj, scc.back());
#include <iostream> return scc;
#include <vector> }
#include <cstdio> };
#include <cstdlib>
#include <map> int main() {
#include <set> int n, m;
#include <cmath> scanf("%d %d", &n, &m);
#include <cstring> graph g(n);
#include <functional> for (int k = 0; k < m; ++k) {
#include <algorithm> int i, j;
#include <unordered_map> scanf("%d %d", &i, &j);
#include <unordered_set> g.add_edge(i - 1, j - 1);
}
using namespace std;
vector<vector<int>> scc = g.strongly_connected_components();
#define fst first vector<int> outdeg(scc.size());
#define snd second vector<int> id(n);
#define all(c) ((c).begin()), ((c).end()) for (int i = 0; i < scc.size(); ++i)
for (int u : scc[i]) id[u] = i;
for (int u = 0; u < n; ++u)
struct graph { for (int v : g.adj[u])
int n; if (id[u] != id[v]) ++outdeg[id[u]];
vector<vector<int>> adj, rdj;
graph(int n) : n(n), adj(n), rdj(n) { } if (count(all(outdeg), 0) != 1) {
void add_edge(int src, int dst) { printf("0\n");
adj[src].push_back(dst); } else {
rdj[dst].push_back(src); int i = find(all(outdeg), 0) - outdeg.begin();
} sort(all(scc[i]));
98
scc[scc.size() - 1].push_back(u);
5.38 SCC Tarjan in_stack[u] = false;
st.pop();
}
stack<int> st;
}
vector<vector<int> > scc;
int low[MAX], disc[MAX], comp[MAX];
int tarjan()
int dfs_time;
{
bool in_stack[MAX];
memset(comp, -1, sizeof(comp));
memset(disc, -1, sizeof(disc));
vi graph[MAX];
memset(low, -1, sizeof(low));
int n; // node count indexed from 1
memset(in_stack, 0, sizeof(in_stack));
dfs_time = 0;
void dfs(int u)
{
while(!st.empty())
low[u] = dfs_time;
st.pop();
disc[u] = dfs_time;
dfs_time++;
for(int i = 1; i <= n; i++)
if(disc[i] == -1)
in_stack[u] = true;
dfs(i);
st.push(u);
int sz = scc.size();
int sz = graph[u].size(), v;
for(int i = 0; i < sz; i++)
for(int i = 0; i < sz; i++)
for(int j = 0; j < (int)scc[i].size(); j++)
{
comp[scc[i][j]] = i;
v = graph[u][i];
return sz;
if(disc[v] == -1)
}
{
dfs(v);
low[u] = min(low[u], low[v]);
}
else if(in_stack[v] == true)
5.39 SPFA
low[u] = min(low[u], disc[v]);
} int dist[MAX], inq[MAX];
void spfa(int source)
if(low[u] == disc[u]) {
{ FOR(i,1,n+1) inq[i]=false, dist[i]=inf; // or INF
99
dist[source]=0; }
queue<int> Q; void cleanup(vi &vtx)
Q.push(source); {
inq[source]=true; for(auto it: vtx)
{
while(!Q.empty()) tree[it].clear();
{ }
int u=Q.front(); }
Q.pop(); bool isancestor(int u, int v) // Check if u is an ancestor of v
FOR(j,0,graph[u].size()) {
{ return (tin[u]<=tin[v]) && (tout[v]<=tout[u]);
int v=graph[u][j]; }
// building the auxiliary tree. Nodes are in vtx
if(dist[u]+cost[u][j]<dist[v]) void sortbyEntry(vi &vtx)
{ {
dist[v]=dist[u]+cost[u][j]; // Sort by entry time
if(!inq[v]) sort(begin(vtx), end(vtx), [](int x, int y){
{ return tin[x]<tin[y];
Q.push(v); });
inq[v]=true; }
} void release(vi &vtx)
} {
} // removing duplicated nodes
inq[u]=false; SORT(vtx);
} vtx.erase(unique(begin(vtx),end(vtx)),end(vtx));
} }
void buildTree(vi &vtx)
{
stack<int> st;
5.40 Tree Construction with Specific Vertices st.push(vtx[0]);
FOR(i,1,vtx.size())
{
/* This code builds an auxiliary tree from the given vertices to do
while(!isancestor(st.top(),vtx[i]))
further operations. Example problem: CF 613D */
st.pop();
tree[st.top()].pb(vtx[i]);
void dfs(int u, int p=0, int d=0)
st.push(vtx[i]);
{
}
tin[u]=++t;
}
parent[u][0]=p;
int work(vi &vtx)
level[u]=d;
{
for(auto v: graph[u])
sortbyEntry(vtx);
{
int sz=vtx.size();
if(v==p) continue;
// Finding all the ancestors, there are few of them
dfs(v,u,d+1);
FOR(i,0,sz-1)
}
{
tout[u]=t;
100
struct complex_base bit_rev[i] = (bit_rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
{ if (bit_rev[i] < i) swap(a[i], a[bit_rev[i]]);
double x, y; }
complex_base(double _x = 0, double _y = 0) { x = _x; y = _y; }
friend complex_base operator-(const complex_base &a, const for (int len = 2; len <= n; len <<= 1)
complex_base &b) { return complex_base(a.x - b.x, a.y - b.y); } {
friend complex_base operator+(const complex_base &a, const double ang = -2 * PI / len;
complex_base &b) { return complex_base(a.x + b.x, a.y + b.y); } complex_base w(1, 0), wn(cos(ang), sin(ang));
friend complex_base operator*(const complex_base &a, const
complex_base &b) { return complex_base(a.x * b.x - a.y * b.y, a.y for (int j = 0; j < (len >> 1); j++, w = w * wn)
* b.x + b.y * a.x); } for (int i = 0; i < n; i += len)
friend void operator/=(complex_base &a, const double &P) { a.x /= P; {
a.y /= P; } complex_base u = a[i + j], v = w * a[i + j + (len >> 1)];
}; a[i + j] = u + v;
a[i + j + (len >> 1)] = u - v;
int bit_rev[MAXN]; }
}
void fft(complex_base *a, int lg)
{ for (int i = 0; i < n; i++)
int n = (1 << lg); a[i] /= n;
for (int i = 1; i < n; i++) }
{
bit_rev[i] = (bit_rev[i >> 1] >> 1) | ((i & 1) << (lg - 1)); complex_base A[MAXN], B[MAXN];
if (bit_rev[i] < i) swap(a[i], a[bit_rev[i]]);
} vector<ll> mult(vector<ll> a, vector<ll> b)
{
for (int len = 2; len <= n; len <<= 1) if (a.size() * b.size() <= 256)
{ {
double ang = 2 * PI / len; vector<ll> ans(a.size() + b.size(), 0);
complex_base w(1, 0), wn(cos(ang), sin(ang)); for (int i = 0; i < (int)a.size(); i++)
for (int j = 0; j < (len >> 1); j++, w = w * wn) for (int j = 0; j < (int)b.size(); j++)
for (int i = 0; i < n; i += len) ans[i + j] += a[i] * b[j];
{
complex_base u = a[i + j], v = w * a[i + j + (len >> 1)]; return ans;
a[i + j] = u + v; }
a[i + j + (len >> 1)] = u - v;
} int lg = 0; while ((1 << lg) < (a.size() + b.size())) ++lg;
} for (int i = 0; i < (1 << lg); i++) A[i] = B[i] = complex_base(0, 0);
} for (int i = 0; i < (int)a.size(); i++) A[i] = complex_base(a[i], 0);
for (int i = 0; i < (int)b.size(); i++) B[i] = complex_base(b[i], 0);
void inv_fft(complex_base *a, int lg)
{ fft(A, lg); fft(B, lg);
int n = (1 << lg); for (int i = 0; i < (1 << lg); i++)
for (int i = 1; i < n; i++) A[i] = A[i] * B[i];
{ inv_fft(A, lg);
103
*pu += t;
vector<ll> ans(a.size() + b.size(), 0); }
for (int i = 0; i < (int)ans.size(); i++) }
ans[i] = (int)(A[i].x + 0.5); }
6.8 Fast Integer Cube and Square Root for (; r >= 0; r -= 3){
res <<= 1;
x = (res * (res + 1) * 3) + 1;
unsigned int fast_sqrt(unsigned int n){
if ((n >> r) >= x){
unsigned int c, g;
res++;
n -= (x << r);
c = g = 0x8000;
}
for (; ;){
}
if ((g * g) > n) g ^= c;
c >>= 1;
return res;
if (!c) return g;
}
g |= c;
}
int main(){
}
}
int fast_cbrt(int n){
int x, r = 30, res = 0;
for (i = 1; i < MAXN; i++){ long long faulhaber(unsigned long long n, int k){
long long x = 1; ///fool::init();
for (j = 0; j < MAX; j++){ return F(n, k);
dp[i][j] = dp[i - 1][j] + x; }
if (dp[i][j] >= MOD) dp[i][j] -= MOD; }
x = (x * i) % MOD;
} int main(){
} fool::init();
} int t, i, j;
long long n, k, res;
/// Returns (1^k + 2^k + 3^k + .... n^k) % MOD
long long F(unsigned long long n, int k){ cin >> t;
if (n < MAXN) return dp[n][k]; while (t--){
cin >> n >> k;
if (n == 1) return 1; res = fool::faulhaber(n, k);
if (n == 2) return (P[k] + 1) % MOD; cout << res << endl;
if (!k) return (n % MOD); }
if (k == 1){ return 0;
n %= MOD; }
return (((n * (n + 1)) % MOD) * inv) % MOD;
}
unsigned long long h = (n << 10LL) | k; /// Change hash function 6.11 Faulhaber’s Formula
according to limits of n and k
long long res = mp[h];
#include <stdio.h>
if (res) return res;
#include <string.h>
#include <stdbool.h>
if (n & 1) res = F(n - 1, k) + expo(n, k);
else{
#define MAX 2510
long long m, z;
#define MOD 1000000007
m = n >> 1;
#define clr(ar) memset(ar, 0, sizeof(ar))
res = (F(m, k) * P[k]) % MOD;
#define read() freopen("lol.txt", "r", stdin)
m--, res++;
int S[MAX][MAX], inv[MAX];
for (int i = 0; i <= k; i++){
z = (F(m, i) * binomial[k][i]) % MOD;
int expo(long long x, int n){
z = (z * P[i]) % MOD;
x %= MOD;
res += z;
long long res = 1;
}
}
while (n){
if (n & 1) res = (res * x) % MOD;
res %= MOD;
x = (x * x) % MOD;
return (mp[h] = res);
n >>= 1;
}
}
113
}
for (int p = n-1; p >= 0; p--) if (irow[p] != icol[p]) {
for (int k = 0; k < n; k++) swap(a[k][irow[p]], a[k][icol[p]]);
}
6.14 Gauss Xor
return det;
}
const int MAXN = (1 << 20);
const int MAXLOG = 64;
int main() {
const int n = 4;
struct basis
const int m = 2;
{
double A[n][n] = { {1,2,3,4},{1,0,1,0},{5,3,2,4},{6,1,4,6} };
int64_t base[MAXLOG];
double B[n][m] = { {1,2},{4,3},{5,6},{8,7} };
VVT a(n), b(n);
void clear()
for (int i = 0; i < n; i++) {
{
a[i] = VT(A[i], A[i] + n);
for(int i = MAXLOG - 1; i >= 0; i--)
b[i] = VT(B[i], B[i] + m);
base[i] = 0;
}
}
double det = GaussJordan(a, b);
void add(int64_t val)
{
// expected: 60
for(int i = MAXLOG - 1; i >= 0; i--)
cout << "Determinant: " << det << endl;
if((val >> i) & 1)
{
// expected: -0.233333 0.166667 0.133333 0.0666667
if(!base[i]) { base[i] = val; return; }
// 0.166667 0.166667 0.333333 -0.333333
else val ^= base[i];
// 0.233333 0.833333 -0.133333 -0.0666667
}
// 0.05 -0.75 -0.1 0.2
}
cout << "Inverse: " << endl;
for (int i = 0; i < n; i++) {
inline int size()
for (int j = 0; j < n; j++)
{
cout << a[i][j] << ’ ’;
int sz = 0;
cout << endl;
for(int i = 0; i < MAXLOG; i++)
}
sz += (bool)(base[i]);
return sz;
// expected: 1.63333 1.3
}
// -0.166667 0.5
// 2.36667 1.7
int64_t max_xor()
// -1.85 -1.35
{
cout << "Solution: " << endl;
int64_t res = 0;
for (int i = 0; i < n; i++) {
for(int i = MAXLOG - 1; i >= 0; i--)
for (int j = 0; j < m; j++)
if(!((res >> i) & 1) && base[i])
cout << b[i][j] << ’ ’;
res ^= base[i];
cout << endl;
}
return res;
116
}
// *****may return empty vector
bool can_create(int64_t val)
{ vector<double> gauss(vector<vector<double>> &a)
for(int i = MAXLOG - 1; i >= 0; i--) {
if(((val >> i) & 1) && base[i]) int n = a.size(), m = a[0].size() - 1;
val ^= base[i];
vector<int> where(m, -1);
return (val == 0); for(int col = 0, row = 0; col < m && row < n; col++)
} {
}; int sel = row;
for(int i = row; i < n; i++)
if(abs(a[i][col]) > abs(a[sel][col]))
sel = i;
6.15 Gaussian 1
if(abs(a[sel][col]) < eps) { where[col] = -1; continue; }
void gauss(vector< vector<double> > &A) {
for(int i = col; i <= m; i++)
int n = A.size(); swap(a[sel][i], a[row][i]);
where[col] = row;
for(int i = 0; i < n; i++){
int r = i; for(int i = 0; i < n; i++)
for(int j = i+1; j < n; j++) if(i != row)
if(fabs(A[j][i]) > fabs(A[r][i])) {
r = j; if(abs(a[i][col]) < eps) continue;
if(fabs(A[r][i]) < EPS) continue; double c = a[i][col] / a[row][col];
if(r != i) for(int j = 0; j <= m; j++)
for(int j = 0; j <= n; j++) a[i][j] -= c * a[row][j];
swap(A[r][j], A[i][j]); }
for(int k = 0; k < n; k++){
if(k != i){ row++;
for(int j = n; j >= i; j--) }
A[k][j] -= A[k][i]/A[i][i]*A[i][j];
} vector<double> ans(m, 0);
} for(int i = 0; i < m; i++)
} if(where[i] != -1)
ans[i] = a[where[i]][m] / a[where[i]][i];
// solve: A[x][n]/A[x][x] for each x
} // Validity check?
// May need to remove the following code
ll x=bigmod(G,(P-1)/M,mod); res.resize(M);
ll y=bigmod(x,P-2,mod); for(ll i=0; i<M; i++) res[i]=A[i]*1LL*B[i]%P;
ntransform(res,1);
w[0][0]=w[1][0]=1LL; }
};
for(ll i=1; i<M; i++)
{
w[0][i]=(w[0][i-1]*x)%P;
w[1][i]=(w[1][i-1]*y)%P; 6.21 Segmented Sieve
}
}
#define MAX 1000010
void ntransform(vector<ll> &a, ll f)
{
#define BASE_SQR 216
for(ll i=0; i<M; i++)
#define BASE_LEN 10010
{
#define BASE_MAX 46656
if(i<rev[i]) swap(a[i], a[rev[i]]);
#define chkbit(ar, i) (((ar[(i) >> 6]) & (1 << (((i) >> 1) & 31))))
}
#define setbit(ar, i) (((ar[(i) >> 6]) |= (1 << (((i) >> 1) & 31))))
for(ll i=1; i<M; i<<=1)
{
int p, primes[BASE_LEN];
for(ll j=0, t=M/(i<<1); j<M; j+=(i<<1))
unsigned int base[(BASE_MAX >> 6) + 5], isprime[(MAX >> 6) + 5];
{
for(ll k=0, l=0; k<i; k++, l+=t)
void Sieve(){
{
clr(base);
ll x=a[j+k+i]*1LL*w[f][l]%P;
int i, j, k;
ll y=a[j+k];
a[j+k+i]=y-x<0?y-x+P:y-x;
for (i = 3; i < BASE_SQR; i++, i++){
a[j+k]=y+x>=P?y+x-P:y+x;
if (!chkbit(base, i)){
}
k = i << 1;
}
for (j = (i * i); j < BASE_MAX; j += k){
}
setbit(base, j);
if(f)
}
{
}
ll x=bigmod(M,P-2,mod);
}
for(ll i=0; i<M; i++) a[i]=a[i]*1LL*x%P;
}
p = 0;
}
for (i = 3; i < BASE_MAX; i++, i++){
void multiply(vector<ll> &X, vector<ll> &Y, vector<ll> &res)
if (!chkbit(base, i)){
{
primes[p++] = i;
init(max(X.size(),Y.size()));
}
for(ll i=0; i<M; i++) A[i]=B[i]=0;
}
for(ll i=0; i<X.size(); i++) A[i]=X[i];
}
for(ll i=0; i<Y.size(); i++) B[i]=Y[i];
ntransform(A,0);
int SegmentedSieve(long long a, long long b){
ntransform(B,0);
long long j, k, x;
res.clear();
int i, d, counter = 0;
122
int l = input[idx][0], r = input[idx][1]; inline int64_t gilbertOrder(int x, int y, int pow, int rotate) {
if (pow == 0) {
if(l>mid) rs.pb(idx); return 0;
else if(r<mid) ls.pb(idx); }
else int hpow = 1 << (pow-1);
{ int seg = (x < hpow) ? (
if(l==r && l==mid) // query is just on mid, (y < hpow) ? 0 : 3
specially handled ) : (
{ (y < hpow) ? 1 : 2
ans[idx] = ((a[mid] % m == 0) ? 2: 1); );
} seg = (seg + rotate) & 3;
else if(l==mid) // starts from mid const int rotateDelta[4] = {3, 0, 0, 1};
{ int nx = x & (x ^ hpow), ny = y & (y ^ hpow);
ans[idx] = dp_right[r][0]; int nrot = (rotate + rotateDelta[seg]) & 3;
} int64_t subSquareSize = int64_t(1) << (2*pow - 2);
else if(r==mid) // ends in mid int64_t ans = seg * subSquareSize;
{ int64_t add = gilbertOrder(nx, ny, pow-1, nrot);
int rem = a[mid] % m; ans += (seg == 1 || seg == 2) ? add : (subSquareSize - add - 1);
return ans;
ans[idx] = dp_left[l][0]; }
ans[idx] = (ans[idx] +
dp_left[l][(m-rem)%m]) % mod; struct Query {
} int l, r, idx; // queries
else int64_t ord; // Gilbert order of a query
{ // call query[i].calcOrder() to calculate the Gilbert orders
// merge both sides and calculate answer for inline void calcOrder() {
current query ord = gilbertOrder(l, r, 21, 0);
for(int j=0; j<m; j++) }
{ };
ans[idx] = (ans[idx] + (dp_left[l][j] // sort the queries based on the Gilbert order
* dp_right[r][(m-j)%m]) % mod) % inline bool operator<(const Query &a, const Query &b) {
mod; return a.ord < b.ord;
} }
}
}
}
// find answer for other queries by divide and conquer 7.4 HakmemItem175
solve(L,mid,ls);
solve(mid+1,R,rs);
/// Only for non-negative integers
}
/// Returns the immediate next number with same count of one bits, -1 on
failure
long long hakmemItem175(long long n){
7.3 Gilbert Curve for Mo if (n == 0) return -1;
long long x = (n & -n);
long long left = (x + n);
128
long long right = ((n ^ left) / x) >> 2; #define FOR(i,a,b) for (int i=(a); i<(b); i++)
long long res = (left | right); #define FORr(i,a,b) for (int i=(a); i>=(b); i--)
return res; #define itrALL(c,itr) for(__typeof((c).begin())
} itr=(c).begin();itr!=(c).end();itr++)
#define lc ((node)<<1)
/// Returns the immediate previous number with same count of one bits, -1 #define rc ((node)<<1|1)
on failure #define VecPrnt(v) FOR(J,0,v.size()) cout<<v[J]<<" "; cout<<endl
long long lol(long long n){ #define endl "\n"
if (n == 0 || n == 1) return -1; #define PrintPair(x) cout<<x.first<<" "<<x.second<<endl
long long res = ~hakmemItem175(~n); #define EPS 1e-9
return (res == 0) ? -1 : res; #define ArrPrint(a,st,en) for(int J=st; J<=en; J++) cout<<a[J]<<" ";
} cout<<endl;
/* Direction Array */
long long expo(long long x, long long n){ long long determinant(int n, long long ar[MAX][MAX]){
long long res = 1; int i, j, free;
long long res = 1;
while (n){
if (n & 1) res = mul(res, x); for (i = 0; i < n; i++){
x = mul(x, x); for (j = 0; j < n; j++){
n >>= 1; if (ar[i][j] < 0) ar[i][j] += MOD;
} }
}
return res;
} free = gauss(n, ar);
if (free == -1) return 0; /// Determinant is 0 so matrix is not
int gauss(int n, long long ar[MAX][MAX]){ invertible, singular or degenerate matrix
long long x, y;
int i, j, k, l, p, counter = 0; for (i = 0; i < n; i++) res = mul(res, ar[i][i]);
if (free & 1) res = MOD - res;
for (i = 0; i < n; i++){ if ((MOD - res) < res) res -= MOD; /// Determinant can be negative so
for (p = i, j = i + 1; j < n && !ar[p][i]; j++){ if determinant is more close to MOD than 0, make it negative
p = j;
} return res;
if (!ar[p][i]) return -1; }
int msb(unsigned x)
{ 7.11 Next Small
union {
double a; int b[2]; #include <stdio.h>
}; #include <string.h>
a = x; #include <stdbool.h>
return (b[1] >> 20) - 1023;
} #define MAX 250010
#define clr(ar) memset(ar, 0, sizeof(ar))
#define read() freopen("lol.txt", "r", stdin)
7.10 Nearest Smaller Values on Left-Right int ar[MAX], L[MAX], R[MAX], stack[MAX], time[MAX];
// Linear time all nearest smaller values, standard stack-based algorithm. void next_small(int n, int* ar, int* L){
// ansv_left stores indices of nearest smaller values to the left in res. int i, j, k, l, x, top = 0;
-1 means no smaller value was found.
// ansv_right likewise looks to the right. v.size() means no smaller for (i = 0; i < n; i++){
value was found. x = ar[i];
void ansv_left(vector<int>& v, vector<int>& res) { if (top && stack[top] >= x){
stack<pair<int, int> > stk; stk.push(make_pair(INT_MIN, v.size())); while (top && stack[top] >= x) k = time[top--];
for (int i = v.size()-1; i >= 0; i--) { L[i] = (i - k + 2);
while (stk.top().first > v[i]) { stack[++top] = x;
res[stk.top().second] = i; stk.pop(); time[top] = k;
} }
stk.push(make_pair(v[i], i)); else{
} L[i] = 1;
while (stk.top().second < v.size()) { stack[++top] = x;
res[stk.top().second] = -1; stk.pop(); time[top] = i + 1;
} }
} }
}
void ansv_right(vector<int>& v, vector<int>& res) { /*** L[i] contains maximum length of the range from i to the left such
stack<pair<int, int> > stk; stk.push(make_pair(INT_MIN, -1)); that the minimum of this range
for (int i = 0; i < v.size(); i++) { is not less than ar[i].
while (stk.top().first > v[i]) { Similarly, R[i] contains maximum length of the range from i to the
res[stk.top().second] = i; stk.pop(); right such that the minimum
} of this range is not less than ar[i]
132
int main(){
int n, i, j, k;
7.13 Russian Peasant Multiplication
scanf("%d", &n);
for (i = 0; i < n; i++) scanf("%d", &ar[i]);
// calculate (a*b)%m
// Particularly useful when a, b, m all are large like 1e18
fill(n, ar, L, R);
ll RussianPeasantMultiplication(ll a, ll b, ll m)
for (i = 0; i < n; i++) printf("%d ", ar[i]);
{
puts("");
ll ret=0;
for (i = 0; i < n; i++) printf("%d ", R[i]);
puts("");
while(b)
for (i = 0; i < n; i++) printf("%d ", L[i]);
{
puts("");
if(b&1)
return 0;
{
}
ret+=a;
if(ret>=m) ret-=m;
}
7.12 Random Number Generation a=(a<<1);
return ret; equation(long double l, long double p, long double r, long double rhs
} = 0.0):
l(l), p(p), r(r), rhs(rhs){}
};
/// Thomas algorithm to solve tri-digonal system of equations in O(n)
7.14 Stable Marriage Problem vector <long double> thomas_algorithm(int n, vector <struct equation> ar){
ar[0].r = ar[0].r / ar[0].p;
// Gale-Shapley algorithm for the stable marriage problem. ar[0].rhs = ar[0].rhs / ar[0].p;
// madj[i][j] is the jth highest ranked woman for man i. for (int i = 1; i < n; i++){
// fpref[i][j] is the rank woman i assigns to man j. long double v = 1.0 / (ar[i].p - ar[i].l * ar[i - 1].r);
// Returns a pair of vectors (mpart, fpart), where mpart[i] gives ar[i].r = ar[i].r * v;
// the partner of man i, and fpart is analogous ar[i].rhs = (ar[i].rhs - ar[i].l * ar[i - 1].rhs) * v;
pair<vector<int>, vector<int> > stable_marriage(vector<vector<int> >& }
madj, vector<vector<int> >& fpref) { for (int i = n - 2; i >= 0; i--) ar[i].rhs = ar[i].rhs - ar[i].r *
int n = madj.size(); ar[i + 1].rhs;
vector<int> mpart(n, -1), fpart(n, -1); vector <long double> res;
vector<int> midx(n); for (int i = 0; i < n; i++) res.push_back(ar[i].rhs);
queue<int> mfree; return res;
for (int i = 0; i < n; i++) { }
mfree.push(i);
}
while (!mfree.empty()) {
int m = mfree.front(); mfree.pop(); 7.16 U128
int f = madj[m][midx[m]++];
if (fpart[f] == -1) { #include <bits/stdtr1c++.h>
mpart[m] = f; fpart[f] = m;
} else if (fpref[f][m] < fpref[f][fpart[f]]) { using namespace std;
mpart[fpart[f]] = -1; mfree.push(fpart[f]);
mpart[m] = f; fpart[f] = m; typedef unsigned long long int U64;
} else {
mfree.push(m); struct U128{
} U64 lo, hi;
} static const U64 bmax = -1;
return make_pair(mpart, fpart); static const size_t sz = 128;
} static const size_t hsz = 64;
t.lo = ~t.lo;
t.hi = ~t.hi; inline static void divide(const U128 &num, const U128 &den, U128
return t; &quo, U128 &rem) {
} if(den == 0) {
int a = 0;
inline U128 &operator +=(const U128 &b) { quo = U128(a / a);
if (lo > bmax - b.lo) ++hi; }
lo += b.lo; U128 n = num, d = den, x = 1, ans = 0;
hi += b.hi;
return *this; while((n >= d) && (((d >> (sz - 1)) & 1) == 0)) {
} x <<= 1;
d <<= 1;
inline U128 &operator -= (const U128 &b){ }
return *this += -b;
} while(x != 0) {
if(n >= d) {
inline U128 &operator *= (const U128 &b) { n -= d;
if (*this == 0 || b == 1) return *this; ans |= x;
if (b == 0){ }
lo = hi = 0; x >>= 1, d >>= 1;
return *this; }
} quo = ans, rem = n;
}
U128 a(*this);
U128 t = b; inline U128 &operator&=(const U128 &b) {
lo = hi = 0; hi &= b.hi;
lo &= b.lo;
for (size_t i = 0; i < sz; i++) { return *this;
if((t & 1) != 0) *this += (a << i); }
t >>= 1;
} inline U128 &operator|=(const U128 &b) {
return *this; hi |= b.hi;
} lo |= b.lo;
return *this;
inline U128 &operator /= (const U128 &b) { }
U128 rem;
divide(*this, b, *this, rem); inline U128 &operator<<=(const U128& rhs) {
return *this; size_t n = rhs.to_int();
} if (n >= sz) {
lo = hi = 0;
inline U128 &operator %= (const U128 &b) { return *this;
U128 quo; }
divide(*this, b, quo, *this);
return *this; if(n >= hsz) {
} n -= hsz;
135
hi = lo; }
lo = 0;
} inline bool operator < (const U128 &b) const {
return (hi == b.hi) ? lo < b.lo : hi < b.hi;
if(n != 0) { }
hi <<= n;
const U64 mask(~(U64(-1) >> n)); inline bool operator >= (const U128 &b) const {
hi |= (lo & mask) >> (hsz - n); return ! (*this < b);
lo <<= n; }
}
return *this; inline U128 operator & (const U128 &b) const {
} U128 a(*this); return a &= b;
}
inline U128 &operator>>=(const U128& rhs) {
size_t n = rhs.to_int(); inline U128 operator << (const U128 &b) const {
if (n >= sz) { U128 a(*this); return a <<= b;
lo = hi = 0; }
return *this;
} inline U128 operator >> (const U128 &b) const {
U128 a(*this); return a >>= b;
if(n >= hsz) { }
n -= hsz;
lo = hi; inline U128 operator * (const U128 &b) const {
hi = 0; U128 a(*this); return a *= b;
} }
x /= 10; simplify();
} while (x != 0); }
inline U128 gcd(U128 a, U128 b){ inline Rational operator+ (const Rational &f) const {
if (b == 0) return a; return Rational(p * f.q + q * f.p, q * f.q);
return gcd(b, a % b); }
} inline Rational operator- (const Rational &f) const {
return Rational(p * f.q - q * f.p, q * f.q);
inline U128 expo(U128 b, U128 e){ }
U128 res = 1; inline Rational operator* (const Rational &f) const {
while (e != 0){ return Rational(p * f.p, q * f.q);
if ((e & 1) != 0) res *= b; }
e >>= 1, b *= b; inline Rational operator/ (const Rational &f) const {
} return Rational(p * f.q, q * f.p);
return res; }
} };
int u = q.front(); // The solution is to build a graph where vertices denote indices of
q.pop(); strings and an edge
itrALL(node[u], it) // from u to v denotes that string[u] occurs in string[v].
{
char ch = it->first; #define ALPHABET_SIZE 26
int v = it->second; #define MAX_NODE 1e6
int j = link[u]; int n; // number of strings
// use map.find() string in[N], p;
while (j != -1 && !node[j][ch])
j = link[j]; int node[MAX_NODE][ALPHABET_SIZE];
if (j != -1)link[v] = node[j][ch]; int root, nnode, link[MAX_NODE], termlink[MAX_NODE], terminal[MAX_NODE];
else link[v] = 0; bool graph[N][N];
q.push(v);
populate(v); // termlink[u] = a link from node u to a node which is a terminal node
} // terminal node is a node where an ending of an input string occurs
} // terminal[node] = the index of the string which ends in node
}
/* Solution:
void traverse() // For every node of the Aho-Corasick structure find and remember the
{ nearest terminal node (termlink[u]) in the suffix-link path; Once again
int len = s.size(); traverse
int now = root; all strings through Aho-Corasick. Every time new symbol is added, add an
FOR(i, 0, len) arc from the node
{ corresponding to the current string (in the graph we build, not
// use map.find() Aho-Corasick) to
while (now != -1 && !node[now][s[i]]) the node of the graph corresponding to the nearest terminal in the
now = link[now]; suffix-link path;
if (now != -1) now = node[now][s[i]]; The previous step will build all essential arcs plus
else now = 0; some other arcs, but they do not affect the next step in any way;
populate(ending[now], i); Find the transitive closure of the graph.
} */
}
void init()
{
root=0;
nnode=0;
9.3 Aho Corasick Occurrence Relation ms(terminal,-1);
ms(termlink,-1);
}
// Suppose we have n<=1000 strings. Total summation of the length of
these strings
void insertword(int idx)
// can be 1e7. Now we are given queries. In each query, we are given
{
indices of
p=in[idx];
// two strings and asked if one of them occurs in another as a substring.
int len=p.size();
// We need to find this relation efficiently. We will use Aho-Corasick.
int now=root;
140
q.push(v);
FOR(i,0,len) }
{ }
int x=p[i]-’a’; }
int v=node[u][i]; // Finally, find transitive closure of the graph. If O(n^3) is possible,
int j=link[u]; we can use
// use map.find() // Floyd-Warshall. Otherwise, run dfs from each node and add an edge from
while(j!=-1 && !node[j][i]) current starting
j=link[j]; // node to each reachable node. An edge in this transitive closure
denotes the occurrence relation.
if(j!=-1) link[v]=node[j][i];
else link[v]=0;
now=level[i].second; }
travis[link[now]]+=travis[now];
} struct Hash {
} ll h1[MAX], h2[MAX];
int n; // length of s
void driver()
{ Hash(char *s, int n): n(n) {
init(); ll th1 = 0, th2 = 0;
FOR(i,0,n) FOR(i, 0, n) {
{ th1 = (th1 + s[i] * pwr1[i]) % mod1;
// input p th2 = (th2 + s[i] * pwr2[i]) % mod2;
insertword(i); h1[i] = th1;
} h2[i] = th2;
// input s }
push_links(); }
traverse(); Hash() {}
// number of occurence of word i in s is travis[endof[i]] pair<ll, ll> getHash(ll i, ll j) {
}
if(i>j) return {0,0};
ll ret1, ret2;
9.5 Double Hash if (!i) {
ret1 = h1[j];
ret2 = h2[j];
const int p1 = 7919;
}
const int mod1 = 1000004249;
else {
const int p2 = 2203;
// Note: may need to do modinverse
const int mod2 = 1000000289;
// in that case, precalc inv1[] and inv2[]
ret1 = (h1[j] - h1[i - 1]) % mod1;
ll pwr1[MAX+7], pwr2[MAX+7];
if (ret1 < 0) ret1 += mod1;
ret2 = (h2[j] - h2[i - 1]) % mod2;
void precalc()
if (ret2 < 0) ret2 += mod2;
{
}
ll pw1 = 1, pw2 = 1;
return MP(ret1, ret2);
}
FOR(i,0,MAX)
};
{
pwr1[i] = pw1;
pwr2[i] = pw2;
the number of occurrences of the strings from the dictionary. If some // insert a word in automaton number ’id’.
string p void insertword(string &s, int val)
from dictionary has several occurrences in s, we should count all of them. {
int len = s.size();
Solution: If we have N strings in the dictionary, maintain log(N) Aho int now = root;
Corasick
automata. The i-th automata contains the first 2^k strings not included FOR(i,0,len)
in the {
previous automata. For example, if we have N = 19, we need 3 automata: int nxt = s[i]-’a’;
{s[1]...s[16]},
{s[17]...s[18]}, and {s[19]}. To answer the query, we can traverse the if(!node[id][now][nxt])
logN automata {
using the given query string. node[id][now][nxt] = ++nnode;
ms(node[id][nnode],0);
To handle addition, first construct an automata using the single string, cnt[nnode]=0;
and then }
while there are two automatons with the same number of strings, we merge now=node[id][now][nxt];
them by }
constructing a new automaton using brute force. cnt[now]+=val;
Complexity becomes // an occurrence of a string happened in ’now’
O(total_length_of_all_string*log(number_of_insert_operations)). // if val=-1, it means an occurrence is removed
}
To handle deletion, we just insert with a value -1 to store in endpoints void insertdict(vector<string> &dict, vector<int> &vals)
of each {
added string. // dict is the dictionary for current automaton
*/ // and vals can be 1 or -1 denoting addition or deletion of
const int N = 3e5+7; // maximum number of nodes corresponding string
const int ALPHA = 26; // alphabate size FOR(i,0,dict.size()) insertword(dict[i],vals[i]);
int node[20][N][ALPHA]; // stores nodes for id-th automaton }
struct ahoCorasick void pushLinks()
{ {
int root, nnode; queue<int> Q; link[root]=-1;
int link[N], cnt[N], id; Q.push(root);
bool dead; while(!Q.empty())
{
void init(int idx) int u = Q.front(); Q.pop();
{
dead = false; id = idx; root = 0; nnode = 0; for(int i=0; i<ALPHA; i++)
ms(node[id][root],0); {
FOR(i,0,nnode+1) cnt[i] = 0; if(!node[id][u][i]) continue;
} int v = node[id][u][i];
void clear() int l = link[u];
{
dead = true; while(l!=-1 && !node[id][l][i]) l = link[l];
} if(l!=-1) link[v] = node[id][l][i];
144
int main()
9.9 KMP 3 {
// ios_base::sync_with_stdio(0);
// cin.tie(NULL); cout.tie(NULL);
string p, t;
// freopen("in.txt","r",stdin);
int pi[MAX], cnt[MAX];
cin>>t>>p;
void prefixFun()
{
148
int main(){ /// v[i] is the minimum k so that the prefix string str[0:i] can be
gets(str); partitioned into k disjoint palindromes
while (gets(str)){ inline vector <int> factorize(const char* str){
printf("%d\n", minlex(str)); int g[32][3], gp[32][3], gpp[32][3];
} int i, j, k, l, d, u, r, x, pg = 0, pgp = 0, pgpp = 0, n =
return 0; strlen(str);
}
clr(g), clr(gp), clr(gpp);
for (int i = 0; i < n; i++) gpl[i][0] = MAX, gpl[i][1] = MAX + 1;
ms(Edge[i],0);
} LL substr_count(int n,char *s)
n=0; {
lastPal=0; VI cnt(128);
} for(int i=0;i<n;i++)
} PTA; cnt[s[i]]++;
for(int i=1;i<128;i++)
cnt[i]+=cnt[i-1];
VI p(n);
9.14 String Split by Delimiter for(int i=0;i<n;i++)
p[--cnt[s[i]]]=i;
template<typename Out> VVI c(1,VI(n));
void split(const std::string &s, char delim, Out result) { int w=0;
std::stringstream ss(s); for(int i=0;i<n;i++)
std::string item; {
while (std::getline(ss, item, delim)) { if(i==0 || s[p[i]]!=s[p[i-1]]) w++;
*(result++) = item; c[0][p[i]] = w-1;
} }
}
for(int k=0,h=1;h<n;k++,h*=2)
std::vector<std::string> split(const std::string &s, char delim) { {
std::vector<std::string> elems; VI pn(n);
split(s, delim, std::back_inserter(elems)); for(int i=0;i<n;i++) {
return elems; pn[i] = p[i] - h;
} if(pn[i]<0) pn[i] += n;
}
// Continuous input VI cnt(w,0);
string line; for(int i=0;i<n;i++)
while( getline(cin,line) ) cnt[c[k][pn[i]]]++;
{ for(int i=1;i<w;i++)
stringstream ss( line ); // initialize kortesi cnt[i]+=cnt[i-1];
int num; vector< int > v; for(int i=n;i--;)
while( ss >> num ) v.push_back( num ); // :P p[--cnt[c[k][pn[i]]]]=pn[i];
sort( v.begin(), v.end() ); w=0;
// print routine c.push_back(VI(n));
} for(int i=0;i<n;i++)
{
if(i==0 || c[k][p[i]] != c[k][p[i-1]]) {
w++;
9.15 Suffix Array 2 } else {
int i1 = p[i] + h; if(i1>=n) i1-=n;
int i2 = p[i-1] + h; if(i2>=n) i2-=n;
// You are given two strings A and B, consisting only of lowercase
if(c[k][i1]!=c[k][i2]) w++;
letters from the English alphabet.
}
// Count the number of distinct strings S, which are substrings of A, but
c[k+1][p[i]] = w-1;
not substrings of B
152
} ll t=q-p-r;
}
t=abs(t);
LL ans = LL(n)*(n-1)/2;
for(int k=1;k<n;k++) prnt(p-t);
{ }
int i=p[k];
int j=p[k-1]; int main()
int cur = 0; {
for (int h=c.size(); h--;) // ios_base::sync_with_stdio(0);
if (c[h][i] == c[h][j]) { // cin.tie(NULL); cout.tie(NULL);
cur += 1<<h; // freopen("in.txt","r",stdin);
i += 1<<h;
j += 1<<h; int test, cases=1;
}
ans-=cur; input();
} solve();
return ans;
} return 0;
}
char s[200005];
int n, m;
} int main()
} {
string s; cin>>s;
void calheight(int *r,int *sa,int n) int n=s.size(), cnt=0;
{
FOR(i,0,s.size())
int i,j,k=0; {
for(i=1;i<=n;i++) rak[sa[i]] = i; r[i]=s[i]-’a’+1;
for(i=0;i<n;height[rak[i++]] = k ) { // prnt(r[i]);
cnt=max(cnt,r[i]);
for(k?k--:0, j=sa[rak[i]-1] ; r[i+k] == r[j+k] ; k ++) ; }
}
r[n]=0; // This is very important, if there are testacases!
} da(r,sa,n+1,cnt+1); // cnt+1 is must, cnt=max of r[i]
calheight(r,sa,n);
int dp[N][22];
for(int i=1; i<=n; i++)
void initRMQ(int n) printf("sa[%d] = %d\n", i, sa[i]);
{
for(int i= 1;i<=n;i++) dp[i][0] = height[i]; for(int i=2; i<=n; i++)
for(int j= 1; (1<<j) <= n; j ++ ){ printf("height[%d] = %d\n", i, height[i]);
for(int i = 1; i + (1<<j) - 1 <= n ; i ++ ) {
dp[i][j] = min(dp[i][j-1] , dp[i + (1<<(j-1))][j-1]); for(int i=1; i<=n; i++)
} printf("rank[%d] = %d\n", sa[i], rak[sa[i]]);
}
// Must call initRMQ(len)
} // To find lcp between any two suffix i and j, call askRMQ(L+1,R)
// where L=min(rak[sa[i]],rak[sa[j]]), R=max(rak[sa[i]],rak[sa[j]]).
int askRMQ(int L,int R)
{
154
FOR(i,0,SA.psz) {
{ public:
endpos[SA.len[i]].pb(i); void insert(int val, int idx, int depth)
} {
for (int i = depth - 1; i >= 0; i--)
ll ans=0; {
bool bit = val & (1 << i);
FORr(i,SA.psz-1,1) // cout<<"bit now: "<<bit<<endl;
{ if (bit)
for(auto it: endpos[i]) {
{ Tree[idx].cntR++;
cnt[SA.link[it]]+=cnt[it]; if (Tree[idx].rIdx == -1)
ans+=(SA.len[it]-SA.len[SA.link[it]]); // distinct {
occurrences Tree[idx].rIdx = ++globalIdx;
// cnt[it] has occurrence of substring ending at node it idx = globalIdx;
} }
} else idx = Tree[idx].rIdx;
}
// cnt[x] has occurrences of state x else
// To calculate occurrence of an input string, we visit the automata {
using the letters Tree[idx].cntL++;
// of the input string and find the last_state where it finishes if (Tree[idx].lIdx == -1)
// The cnt[last_state] should be the occurrence of this string {
Tree[idx].lIdx = ++globalIdx;
prnt(ans); idx = globalIdx;
}
return 0; else idx = Tree[idx].lIdx;
} }
}
}
int query(int val, int compVal, int idx, int depth)
9.19 Trie 1 {
int ans = 0;
for (int i = depth - 1; i >= 0; i--)
struct Node
{
{
bool valBit = val & (1 << i);
int cntL, cntR, lIdx, rIdx;
bool compBit = compVal & (1 << i);
Node()
if (compBit)
{
{
cntL = cntR = 0;
if (valBit)
lIdx = rIdx = -1;
{
}
ans += Tree[idx].cntR;
};
idx = Tree[idx].lIdx;
Node Tree[MAX];
}
int globalIdx = 0;
else
class Trie
158
int c=getId(s[i]);
#define MAX 100010
if (nxt[v][c]==-1) #define min(a,b) ((a)<(b) ? (a):(b))
{ #define max(a,b) ((a)>(b) ? (a):(b))
ms(nxt[sz],-1); #define clr(ar) memset(ar, 0, sizeof(ar))
nxt[v][c]=sz++; #define read() freopen("lol.txt", "r", stdin)
en[sz]=0;
// created[sz] = true; char str[MAX];
} int n, Z[MAX];
v = nxt[v][c]; void ZFunction(){ /// Z[i] = lcp of the suffix starting from i with str
} int i, j, k, l, r, p;
++en[v]; Z[0] = n, l = 0, r = 0;
} for (i = 1; i < n; i++){
if (i > r){
int search (char *tmp, int l) { k = 0;
while ((i + k) < n && str[i + k] == str[k]) k++;
int v = 0; Z[i] = k;
if (Z[i]) l = i, r = i + Z[i] - 1;
for (int i = 0; i < l; ++i) { }
else{
int c=getId(tmp[i]); p = i - l;
if (Z[p] < (r - i + 1)) Z[i] = Z[p];
if (nxt[v][c]==-1) else{
return 0; k = r + 1;
while (k < n && str[k - i] == str[k]) k++;
v = nxt[v][c]; l = i, r = k - 1;
} Z[i] = (r - l + 1);
return en[v]; }
} }
}
void init() }
{
sz=1; /// Z[i] = lcp of the suffix starting from i with str
en[0]=0; void ZFunction(char* str){ /// hash = 998923
ms(nxt[0],-1); int i, l, r, x;
}
l = 0, r = 0;
for (i = 1; str[i]; i++){
Z[i] = max(0, min(Z[i - l], r - i));
9.21 Z Algorithm while (str[i + Z[i]] && str[Z[i]] == str[i + Z[i]]) Z[i]++;
if ((i + Z[i]) > r) l = i, r = i + Z[i];
}
#include <stdio.h>
Z[0] = i;
#include <string.h>
}
#include <stdbool.h>
160
int main(){
scanf("%s", str);
n = strlen(str);
ZFunction();
return 0;
}