Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Codebook.tex
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,5 @@
\tableofcontents
\end{multicols}
\clearpage

\end{document}
11 changes: 6 additions & 5 deletions VIM/3_tips.tex
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
\begin{itemize}
\setlength\itemsep{-0.5em}
\item Segment Tree, DP, bitwise DP, 枚舉, 枚舉+剪枝, Disjoint Set
\item Priority Queue, 單調隊列, Prefix Sum, 偏序
\item Segment Tree, DP, bitwise DP, 配合ds加速dp, 枚舉, 枚舉+剪枝, branch and bound, binarysearch, meet in middle
\item Priority Queue, 單調隊列, Prefix Sum, 偏序, 斜率優化, cdq, Disjoint Set
\item Graph: SCC, AP, Bridge, LCA, 2-SAT
\item Flow, Min-cost Max-flow, Bipartite
\item Primal test, PollardRho, KMP, Rabin Fingerprint, FFT
\item Convex Hull, 旋轉卡尺, 極角排序
\item Flow, Min-cost Max-flow, Bipartite, Cover, Matching
\item Flow 相關技巧 : increment capacity one by one, binary search on Constructing limit. 倍增點並計算貢獻值(WF: memory), 把點拆成in, out兩個點。
\item Primal test, PollardRho, KMP, Rabin Fingerprint(BIT), FFT
\item Convex Hull, 旋轉卡尺, 極角排序, slicing, relabel
\end{itemize}
113 changes: 72 additions & 41 deletions data_structure/Li_Chao_Tree.cpp
Original file line number Diff line number Diff line change
@@ -1,52 +1,83 @@
// Miminimum Li Chao Tree
typedef long long ftype;
typedef complex<ftype> point;
#define x real
#define y imag

ftype dot(point a, point b) {
return (conj(a) * b).x();
}

ftype f(point a, ftype x) {
return dot(a, {x, 1});
}

const int maxn = 2e5;

point line[4 * maxn];

const ll inf = 1e18;
const int maxx = 1e6;
struct line
{
ll m, b;
line() { m = b = inf; }
line(ll mm, ll bb){m = mm, b = bb;}
ll y(ll x){
if(m == inf || b == inf)
return inf;
return m * x + b;
}
};
line segs[4 * maxx];
/*
a line is y = k * x + b, using point to represent it.
y = (k, b) * (x, 1) (dot operation).
*/
// y = nw.real() * x + nw.imag().
void add_line(point nw, int idx = 1, int l = 0, int r = maxn)
void add_line(line cur, int idx = 1, int l = 0, int r = maxx)
{
int m = (l + r) / 2;
bool lef = f(nw, l) < f(line[idx], l);
bool mid = f(nw, m) < f(line[idx], m);
if(mid) {
swap(line[idx], nw);
}
if(r - l == 1) {
if(l == r){
if(cur.y(l) < segs[idx].y(l)){
segs[idx] = cur;
}
return;
} else if(lef != mid) {
add_line(nw, 2 * idx, l, m);
} else {
add_line(nw, 2 * idx + 1, m, r);
}
int mid = (l + r) >> 1;
if(cur.m > segs[idx].m){
swap(cur, segs[idx]);
}
if(cur.y(mid) < segs[idx].y(mid)){
swap(cur, segs[idx]);
add_line(cur, idx * 2, l, mid);
}
else{
add_line(cur, idx * 2 + 1, mid + 1, r);
}
}

// get minimum in some point x;
ftype get(int x, int idx = 1, int l = 0, int r = maxn)
// get minimum in some line x;
ll query(int x, int idx = 1, int l = 0, int r = maxx)
{
int m = (l + r) / 2;
if(r - l == 1) {
return f(line[idx], x);
} else if(x < m) {
return min(f(line[idx], x), get(x, 2 * idx, l, m));
} else {
return min(f(line[idx], x), get(x, 2 * idx + 1, m, r));
}
ll cur = segs[idx].y(x);
if(l == r)
return cur;
int mid = (l + r) >> 1;
if (x <= mid)
return min(cur, query(x, idx * 2, l, mid));
else
return min(cur, query(x, idx * 2 + 1, mid + 1, r));
}

// if the line slope is non-increasing. and query(x) is increasing.
// dp[i] = min{s[i] * f[j] + dp[j], for all j < i}. f[i] is non-increasing. s[i] increasing.
ll inters(line l1,line l2){
return (l2.b-l1.b)/(l1.m-l2.m);
}
bool check(line l1,line l2,line l3){
ll l12=inters(l1,l2);
ll l23=inters(l2,l3);
return l23<l12;
}
ll s[maxn], f[maxn], dp[maxn];
int main(){
int n,k; cin >> n >> k;
for(int i=1;i<=n;i++) cin >> s[i];
for(int i=1;i<=n;i++) cin >> f[i];

deque<line> q;
q.push_front({k,0});

for(int i=1;i<=n;i++){
int x=s[i];
while(q.size()>=2 && q[0].y(x)>q[1].y(x)) q.pop_front();
dp[i]=q.front().y(x);
line now={f[i],dp[i]};

if(q.back().a==now.a) continue;
while(q.size()>=2 && check(q[q.size()-2],q[q.size()-1],now)) q.pop_back();
q.push_back(now);
}
cout << dp[n] << '\n';
}
64 changes: 64 additions & 0 deletions data_structure/segmentTree_2D.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
int num[501][501], N, M; // input here
struct seg_2D {
struct node {
int data;
node *lc, *rc;
} * root;
node *merge(node *a, node *b, int l, int r) {
node *p = new node;
p->data = max(a->data, b->data);
if (l == r) return p;
int m = l + r >> 1;
p->lc = merge(a->lc, b->lc, l, m);
p->rc = merge(a->rc, b->rc, m + 1, r);
return p;
}
node *build(int l, int r, int x) {
node *p = new node;
if (l == r) return p->data = num[x][l], p;
int m = l + r >> 1;
p->lc = build(l, m, x), p->rc = build(m + 1, r, x);
p->data = max(p->lc->data, p->rc->data);
return p;
}
int query(int L, int R, int l, int r, node *p) {
if (L <= l && R >= r) return p->data;
int m = l + r >> 1, re = 0;
if (L <= m) re = query(L, R, l, m, p->lc);
if (R > m)
re = max(re, query(L, R, m + 1, r, p->rc));
return re;
}
};
struct seg_1D {
struct node {
seg_2D data;
node *lc, *rc;
} * root;
node *s_build(int l, int r) {
node *p = new node;
if (l == r)
return p->data.root = p->data.build(1, M, l), p;
int m = l + r >> 1;
p->lc = s_build(l, m), p->rc = s_build(m + 1, r);
p->data.root = p->data.merge(
p->lc->data.root, p->rc->data.root, 1, M);
return p;
}
int s_query(int L, int R, int l, int r, node *p,
int yl, int yr) {
if (L <= l && R >= r)
return p->data.query(yl, yr, 1, M, p->data.root);
int m = l + r >> 1, re = 0;
if (L <= m)
re = s_query(L, R, l, m, p->lc, yl, yr);
if (R > m)
re = max(
re, s_query(L, R, m + 1, r, p->rc, yl, yr));
return re;
}
void init() { root = s_build(1, N); }
int query(int xl, int xr, int yl, int yr) {
return s_query(xl, xr, 1, N, root, yl, yr);
}
};
54 changes: 54 additions & 0 deletions geometry/CDQ.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// for each j store number of pair (i, j) such that Xi <= Xj and Yi <= Yj and Zi <= Zj
struct point{
int x, y, z, idx;
point(){x = y = z = 0;}
point(int a, int b, int c, int id):x(a), y(b), z(c), idx(id){}
bool operator==(const point &a){
return x == a.x && y == a.y && z == a.z;
}
};
const int maxn = 100001;
vec<point> pts;
point staticArr[maxn];
int ans[maxn], mt[maxn]; // mt is an binary index tree

void cdq(int l, int r){
if(l == r)
return ;
int mid = (l + r) >> 1;
cdq(l, mid);
cdq(mid + 1, r);

vec<int> arr;
for(int i = l ;i <= r; i++)
arr.eb(pts[i].z);
sort(al(arr)); arr.resize(unique(al(arr)) - arr.begin());
fill(mt, mt + arr.size()+1, 0);

int cpidx = 0, lid = l, rid = mid + 1;
for(rid = mid+1; rid <= r; rid++){
while(lid <= mid && pts[lid].y <= pts[rid].y){
add(upper_bound(al(arr), pts[lid].z) - arr.begin(), 1);
staticArr[cpidx++] = pts[lid];
lid++;
}
ans[pts[rid].idx] += query(upper_bound(al(arr), pts[rid].z) - arr.begin());
staticArr[cpidx++] = pts[rid];
}
while(lid <= mid) staticArr[cpidx++] = pts[lid++];
for(int i = l; i <= r; i++) pts[i] = staticArr[ i - l ];
}
int main(){
int n, idx = 0; cin >> n; fill(ans, ans+n, 0); pts.resize(n);
for(point& e: pts)
cin >> e.x >> e.y >> e.z; e.idx = idx++;
auto cmp_1 = [](point&a , point &b){ return a.x == b.x ? (a.y == b.y ? a.z < b.z : a.y < b.y ): a.x < b.x; };
sort(al(pts), cmp_1);
for(int i = n-2; i >= 0 ; i--){
if(pts[i] == pts[i+1]){
ans[pts[i].idx] = ans[pts[i+1].idx] + 1;
// calculate ans that (pts[i] == pts[j] && i > j) as for ans (pts[i] == pts[j] && i < j) will be calculate in normal process
}
}
cdq(0, n-1);
}
Empty file removed geometry/slicing.cpp
Empty file.
Loading