teamnote history merge
This commit is contained in:
102
2024fall/source/DS/LiChaoTree.cpp
Normal file
102
2024fall/source/DS/LiChaoTree.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include<bits/stdc++.h>
|
||||
|
||||
#define all(v) (v).begin(), (v).end()
|
||||
#define rall(v) (v).rbegin(), (v).rend()
|
||||
|
||||
#define getint(n) int n; scanf("%d%*c", &n)
|
||||
#define getll(n) ll n; scanf("%lld%*c", &n)
|
||||
#define inta int a; scanf("%d%*c", &a)
|
||||
#define intab int a,b; scanf("%d%*c%d%*c", &a,&b)
|
||||
|
||||
#define forr(i, n) for(int i=1; i <= (n); i++)
|
||||
#define fors(i, s, e) for(int i = (s); i<=(e); i++)
|
||||
#define fore(i, e, s) for(int i = (e); i >= s; i--)
|
||||
|
||||
#define pb push_back
|
||||
#define fi first
|
||||
#define se second
|
||||
|
||||
using namespace std;
|
||||
|
||||
using ll = long long;
|
||||
using pii = pair<int,int>; using pll = pair<ll, ll>;
|
||||
using vi = vector<int>; using vii = vector<pii>;
|
||||
struct Line
|
||||
{
|
||||
ll a=0, b=(ll)2e18+7;
|
||||
ll operator()(ll x){return a*x+b;}
|
||||
Line():a(0),b((ll)2e18+7){}
|
||||
Line(ll a, ll b):a(a), b(b){}
|
||||
};
|
||||
|
||||
ll middle(ll s, ll e){return (s+e+(ll)2e18)/2-(ll)1e18;}
|
||||
struct Node
|
||||
{
|
||||
Node *l=0, *r=0;
|
||||
Line v;
|
||||
Node():l(0), r(0), v(Line()){}
|
||||
};
|
||||
void insert(Node* node, Line v, ll l, ll r, ll s, ll e)
|
||||
{
|
||||
ll mid=middle(s, e);
|
||||
if(e < l or r < s) return;
|
||||
if(s == e)
|
||||
{
|
||||
node->v = (node->v(s) < v(s))?node->v:v;
|
||||
return;
|
||||
}
|
||||
if(!node->l) node->l = new Node();
|
||||
if(!node->r) node->r = new Node();
|
||||
|
||||
if(l <= s and e <= r)
|
||||
{
|
||||
if(node->v(s) >= v(s) and node->v(e) >= v(e)){node->v = v; return;}
|
||||
if(node->v(s) <= v(s) and node->v(e) <= v(e)) return;
|
||||
insert(node->l, v, l, r, s, mid);
|
||||
insert(node->r, v, l, r, mid+1, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
insert(node->l, v, l, r, s, mid);
|
||||
insert(node->r, v, l, r, mid+1, e);
|
||||
}
|
||||
}
|
||||
ll query(Node* node, ll x, ll s, ll e)
|
||||
{
|
||||
if(!node) return (ll)2e18+7;
|
||||
if(x < s or e < x) return (ll)2e18+7;
|
||||
if(s == e) return node->v(x);
|
||||
|
||||
ll mid = middle(s, e);
|
||||
return min({query(node->l, x, s,mid), query(node->r, x, mid+1, e), node->v(x)});
|
||||
}
|
||||
// 전체 구간을 미리 고정해 놓아야 함.
|
||||
// (const int L = -1e9, R = 1e9);
|
||||
// Insert : insert(root, Line 객체, l, r, L, R);
|
||||
// Query : query(root, x, L, R);
|
||||
int main()
|
||||
{
|
||||
Node *root = new Node();
|
||||
getint(n); getint(Q);
|
||||
forr(i, n)
|
||||
{
|
||||
getll(l); getll(r); getll(a); getll(b);
|
||||
insert(root, Line(a,b), l,r-1,(ll)-1e9-7, (ll)1e9+7);
|
||||
}
|
||||
while(Q--)
|
||||
{
|
||||
getint(q);
|
||||
if(q == 0)
|
||||
{
|
||||
getll(l); getll(r); getll(a); getll(b);
|
||||
insert(root, Line(a,b), l,r-1,(ll)-1e9-7, (ll)1e9+7);
|
||||
}
|
||||
if(q == 1)
|
||||
{
|
||||
getll(x);
|
||||
ll ans = query(root, x,(ll)-1e9-7, (ll)1e9+7);
|
||||
if(ans == (ll)2e18+7) printf("INFINITY\n");
|
||||
else printf("%lld\n", ans);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
2024fall/source/DS/PBDS.cpp
Normal file
19
2024fall/source/DS/PBDS.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include<ext/pb_ds/assoc_container.hpp>
|
||||
using namespace __gnu_pbds;
|
||||
|
||||
template<typename T>
|
||||
using indexed_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
|
||||
|
||||
indexed_set<int> s;
|
||||
s.insert(3); s.insert(2); s.insert(3);
|
||||
s.insert(9); s.insert(7);
|
||||
//2 3 7 9
|
||||
|
||||
s.insert(5); //2 3 5 7 9
|
||||
s.erase(5); //2 3 7 9
|
||||
|
||||
auto x = s.find_by_order(2); // *x : 7
|
||||
|
||||
s.order_of_key(6) // 2
|
||||
s.order_of_key(7) // 2
|
||||
s.order_of_key(8) // 3
|
||||
177
2024fall/source/DS/SegmentTree.cpp
Normal file
177
2024fall/source/DS/SegmentTree.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
namespace GMS
|
||||
{
|
||||
template<typename D, D (*join)(D,D), D _e>
|
||||
class Segtree
|
||||
{
|
||||
class Node
|
||||
{
|
||||
Node *l, *r;
|
||||
int s,e; D v;
|
||||
public:
|
||||
Node(int s, int e) :l(0), r(0), s(s), e(e), v(_e){};
|
||||
~Node(){delete l; delete r;}
|
||||
|
||||
template<typename Dini>
|
||||
friend void init(Node* node, Dini arr[] = NULL)
|
||||
{
|
||||
int s = node->s, e=node->e, mid=(s+e)/2;
|
||||
if(s == e)
|
||||
{
|
||||
node->v = D(arr?arr[s]:_e);
|
||||
return;
|
||||
}
|
||||
|
||||
node->l = new Node(s, mid);
|
||||
init(node->l, arr);
|
||||
node->r = new Node(mid+1, e);
|
||||
init(node->r, arr);
|
||||
|
||||
node->v = join(node->l->v, node->r->v);
|
||||
}
|
||||
friend D _query(Node* node, int a, int b)
|
||||
{
|
||||
int s=node->s, e=node->e;
|
||||
if(a <= s and e <= b) return node->v;
|
||||
if(b < s or e < a) return _e;
|
||||
|
||||
return join(_query(node->l, a, b), _query(node->r, a, b));
|
||||
}
|
||||
friend void _update
|
||||
(Node* node, int i, function<D(D)> upd)
|
||||
{
|
||||
int s=node->s, e=node->e;
|
||||
if(i < s or e < i) return;
|
||||
if(s == e)
|
||||
{
|
||||
node->v = upd(node->v);
|
||||
return;
|
||||
}
|
||||
|
||||
_update(node->l, i, upd);
|
||||
_update(node->r, i, upd);
|
||||
|
||||
node->v = join(node->l->v, node->r->v);
|
||||
}
|
||||
};
|
||||
|
||||
Node *root;
|
||||
public:
|
||||
|
||||
template<typename Dini>
|
||||
Segtree(int s,int e, Dini arr[] = NULL)
|
||||
{
|
||||
root = new Node(s, e);
|
||||
init(root, arr);
|
||||
}
|
||||
~Segtree(){delete root;}
|
||||
D query(int s, int e)
|
||||
{return _query(root, s, e);}
|
||||
void update(int i, function<D(D)> upd)
|
||||
{_update(root, i, upd);}
|
||||
};
|
||||
|
||||
|
||||
template<typename D, D (*join)(D,D), D _e, typename L, D (*apply)(D, L, int), L (*give)(L, L), L _l>
|
||||
class LZSegtree
|
||||
{
|
||||
class Node
|
||||
{
|
||||
Node *l, *r;
|
||||
int s,e;
|
||||
D v; L lz;
|
||||
|
||||
void prop()
|
||||
{
|
||||
v = apply(v, lz, e-s+1);
|
||||
if(l) l->lz = give(l->lz, lz);
|
||||
if(r) r->lz = give(r->lz, lz);
|
||||
|
||||
lz = _l;
|
||||
}
|
||||
|
||||
public:
|
||||
Node(int s, int e)
|
||||
:l(0), r(0), s(s), e(e), v(_e), lz(_l){};
|
||||
~Node(){delete l; delete r;}
|
||||
|
||||
template<typename Dini>
|
||||
friend void init(Node* node, Dini arr[] = NULL)
|
||||
{
|
||||
int s = node->s, e=node->e, mid=(s+e)/2;
|
||||
if(s == e)
|
||||
{
|
||||
node->v = D(arr?arr[s]:_e);
|
||||
return;
|
||||
}
|
||||
|
||||
node->l = new Node(s, mid);
|
||||
init(node->l, arr);
|
||||
node->r = new Node(mid+1, e);
|
||||
init(node->r, arr);
|
||||
|
||||
node->v = join(node->l->v, node->r->v);
|
||||
}
|
||||
friend D _query(Node* node, int a, int b)
|
||||
{
|
||||
node->prop();
|
||||
int s=node->s, e=node->e;
|
||||
if(a <= s and e <= b) return node->v;
|
||||
if(b < s or e < a) return _e;
|
||||
|
||||
return join(_query(node->l, a, b), _query(node->r, a, b));
|
||||
}
|
||||
friend void _update
|
||||
(Node* node, int a, int b, function<L(L)> upd)
|
||||
{
|
||||
node->prop();
|
||||
int s=node->s, e=node->e;
|
||||
if(b < s or e < a) return;
|
||||
if(a <= s and e <= b)
|
||||
{
|
||||
node->lz = upd(node->lz);
|
||||
node->prop();
|
||||
return;
|
||||
}
|
||||
|
||||
_update(node->l, a, b, upd);
|
||||
_update(node->r, a, b, upd);
|
||||
|
||||
node->v = join(node->l->v, node->r->v);
|
||||
}
|
||||
};
|
||||
|
||||
Node *root;
|
||||
public:
|
||||
|
||||
template<typename Dini>
|
||||
LZSegtree(int s,int e, Dini arr[] = NULL)
|
||||
{
|
||||
root = new Node(s, e);
|
||||
init(root, arr);
|
||||
}
|
||||
~LZSegtree(){delete root;}
|
||||
D query(int s, int e){return _query(root, s, e);}
|
||||
void update(int s, int e, function<L(L)> upd){_update(root, s, e, upd);}
|
||||
};
|
||||
} // namespace GMS
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
#define data _data
|
||||
|
||||
struct data
|
||||
{
|
||||
int m, m_cnt;
|
||||
constexpr data(int m):m(m), m_cnt(1){}
|
||||
constexpr data(int m, int m_cnt):m(m), m_cnt(m_cnt){}
|
||||
};
|
||||
data join(data A, data B)
|
||||
{
|
||||
if(A.m == B.m) return data(A.m, A.m_cnt+B.m_cnt);
|
||||
if(A.m < B.m) return A;
|
||||
else return B;
|
||||
}
|
||||
data apply(data A, int lz, int len)
|
||||
{return {A.m+lz, A.m_cnt};}
|
||||
int give(int a, int b){return a+b;}
|
||||
|
||||
using Seg = GMS::LZSegtree<data, join, {(int)1e9, 0}, int, apply, give, 0>;
|
||||
278
2024fall/source/DS/SplayTree.cpp
Normal file
278
2024fall/source/DS/SplayTree.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
struct Node
|
||||
{
|
||||
Node *p, *l, *r;
|
||||
int key, cnt;
|
||||
ll val; ll m, M, sum; ll lazy;
|
||||
bool flip;
|
||||
|
||||
Node(int key, ll val):p(0),l(0), r(0), key(key), cnt(1), val(val), m(val), M(val), sum(val), lazy(0), flip(0){}
|
||||
|
||||
void fix()
|
||||
{
|
||||
cnt = 1+(l?l->cnt:0)+(r?r->cnt:0);
|
||||
sum = val+(l?l->sum:0)+(r?r->sum:0);
|
||||
m = min({val, (l?l->m:inf), (r?r->m:inf)});
|
||||
M = max({val, (l?l->M:-1), (r?r->M:-1)});
|
||||
}
|
||||
void prop()
|
||||
{
|
||||
if(flip)
|
||||
{
|
||||
swap(l, r);
|
||||
if(l) l->flip = !l->flip;
|
||||
if(r) r->flip = !r->flip;
|
||||
|
||||
flip = false;
|
||||
}
|
||||
if(lazy)
|
||||
{
|
||||
val += lazy; sum += cnt * lazy;
|
||||
if(l) l->lazy += lazy;
|
||||
if(r) r->lazy += lazy;
|
||||
|
||||
lazy = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} *root;
|
||||
struct SplayTree
|
||||
{
|
||||
Node *root = NULL, *rp = NULL;
|
||||
|
||||
SplayTree(){}
|
||||
SplayTree(Node *rt)
|
||||
{
|
||||
if(!rt) return;
|
||||
|
||||
root = rt;
|
||||
rp = rt->p;
|
||||
}
|
||||
|
||||
void mop(Node *node)
|
||||
{
|
||||
if(node == root) node->prop();
|
||||
else mop(node->p);
|
||||
|
||||
if(node->l) node->l->prop();
|
||||
if(node->r) node->r->prop();
|
||||
}
|
||||
|
||||
void rotate(Node *node)
|
||||
{
|
||||
if(!root) return;
|
||||
|
||||
if(node->p == rp) return;
|
||||
if(node->p->l == node)
|
||||
{
|
||||
Node *p = node->p, *g = p->p;
|
||||
Node *a = node->l, *b = node->r, *c = p->r;
|
||||
|
||||
p->l = b; if(b) b->p = p;
|
||||
p->r = c; if(c) c->p = p;
|
||||
|
||||
node->l = a; if(a) a->p = node;
|
||||
node->r = p; p->p = node;
|
||||
|
||||
node->p = g; if(g) (g->l == p?g->l:g->r) = node;
|
||||
|
||||
p->fix(); node->fix();
|
||||
|
||||
if(p == root) root = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
Node *p = node->p, *g = p->p;
|
||||
Node *a = p->l, *b = node->l, *c = node->r;
|
||||
|
||||
p->l = a; if(a) a->p = p;
|
||||
p->r = b; if(b) b->p = p;
|
||||
|
||||
node->l = p; p->p = node;
|
||||
node->r = c; if(c) c->p = node;
|
||||
|
||||
node->p = g; if(g) (g->l == p?g->l:g->r) = node;
|
||||
|
||||
p->fix(); node->fix();
|
||||
|
||||
if(p == root) root = node;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void splay(Node* node)
|
||||
{
|
||||
if(!root) return;
|
||||
assert(node); mop(node);
|
||||
|
||||
while(node->p != rp)
|
||||
{
|
||||
Node *p, *g;
|
||||
p = node->p; g = p->p;
|
||||
|
||||
if(g == rp) rotate(node);
|
||||
else if((p->l == node) == (g->l == p))
|
||||
rotate(p), rotate(node);
|
||||
else rotate(node), rotate(node);
|
||||
}
|
||||
|
||||
root = node;
|
||||
}
|
||||
|
||||
Node* insert(int key, ll val)
|
||||
{
|
||||
if(!root)
|
||||
{
|
||||
root = new Node(key, val);
|
||||
return root;
|
||||
}
|
||||
else
|
||||
{
|
||||
Node *now = root;
|
||||
while(true)
|
||||
{
|
||||
if(now->key == key) return NULL;
|
||||
else if(now->key > key)
|
||||
{
|
||||
if(!now->l) break;
|
||||
now = now->l;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!now->r) break;
|
||||
now = now->r;
|
||||
}
|
||||
}
|
||||
|
||||
Node *ret;
|
||||
if(now->key > key)
|
||||
{
|
||||
ret = now->l = new Node(key, val);
|
||||
now->l->p = now;
|
||||
splay(now->l);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = now->r = new Node(key, val);
|
||||
now->r->p = now;
|
||||
splay(now->r);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*Node* find(int key)
|
||||
{
|
||||
Node* now = root;
|
||||
if(!now) return NULL;
|
||||
while(true)
|
||||
{
|
||||
if(key == now->key) break;
|
||||
else if(key < now->key)
|
||||
{
|
||||
if(!now->l) break;
|
||||
now = now->l;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!now->r) break;
|
||||
now = now->r;
|
||||
}
|
||||
}
|
||||
|
||||
splay(now);
|
||||
return key == now->key?now:NULL;
|
||||
}
|
||||
|
||||
void erase(int key)
|
||||
{
|
||||
if(!find(key)) return;
|
||||
if(root->l and root->r)
|
||||
{
|
||||
Node* e = root;
|
||||
root = root->l; root->p = NULL;
|
||||
|
||||
Node* now = root;
|
||||
while(now->r) now = now->r;
|
||||
now->r = e->r;
|
||||
e->r->p = now;
|
||||
splay(now);
|
||||
|
||||
delete e;
|
||||
}
|
||||
else if(root->l)
|
||||
{
|
||||
Node* now = root;
|
||||
root = root->l; root->p = NULL;
|
||||
delete now;
|
||||
}
|
||||
else if(root->r)
|
||||
{
|
||||
Node* now = root;
|
||||
root = root->r; root->p = NULL;
|
||||
delete now;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete root;
|
||||
root = NULL;
|
||||
}
|
||||
}*/
|
||||
|
||||
Node* find_kth(int k) // 0-indexed
|
||||
{
|
||||
assert(root);
|
||||
assert(root->cnt > k);
|
||||
Node *now = root; now->prop();
|
||||
while(true)
|
||||
{
|
||||
while(now->l and now->l->cnt > k) now = now->l, now->prop();
|
||||
k -= now->l?now->l->cnt:0;
|
||||
|
||||
if(k == 0) break;
|
||||
k--; now = now->r;
|
||||
now->prop();
|
||||
}
|
||||
|
||||
splay(now);
|
||||
return now;
|
||||
}
|
||||
Node* gather(int s, int e)
|
||||
{
|
||||
find_kth(e+1);
|
||||
SplayTree(root->l).find_kth(s-1);
|
||||
|
||||
assert(root->l->r);
|
||||
return root->l->r;
|
||||
}
|
||||
void update(int i, int j, ll val)
|
||||
{
|
||||
Node *node = gather(i, j);
|
||||
|
||||
node->lazy += val; node->prop();
|
||||
node->p->fix(); node->p->p->fix();
|
||||
}
|
||||
void reverse(int i, int j)
|
||||
{
|
||||
Node *node = gather(i, j);
|
||||
node->flip = !node->flip;
|
||||
}
|
||||
|
||||
void p_vals(int n){p_vals(root, 0, false, n);}
|
||||
void p_vals(Node* node, ll lz, bool flip, int n)
|
||||
{
|
||||
lz += node->lazy; flip ^= node->flip;
|
||||
if(!flip)
|
||||
{
|
||||
if(node->l) p_vals(node->l, lz, flip, n);
|
||||
if(!(node->key == 0 or node->key == n+1)) printf("%lld ", node->val+lz);
|
||||
if(node->r) p_vals(node->r, lz, flip, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(node->r) p_vals(node->r, lz, flip, n);
|
||||
if(!(node->key == 0 or node->key == n+1)) printf("%lld ", node->val+lz);
|
||||
if(node->l) p_vals(node->l, lz, flip, n);
|
||||
}
|
||||
}
|
||||
};
|
||||
86
2024fall/source/DS/UF_QUndo.cpp
Normal file
86
2024fall/source/DS/UF_QUndo.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
struct dsu_pb
|
||||
{
|
||||
const int N;
|
||||
vi par; stack<pair<pii, pii> > s;
|
||||
|
||||
dsu_pb(int N):N(N), par(N)
|
||||
{
|
||||
fors(i, 0, N-1) par[i] = -1;
|
||||
}
|
||||
int root(int i)
|
||||
{
|
||||
if(par[i] < 0) return i;
|
||||
return root(par[i]);
|
||||
}
|
||||
bool join(int i, int j)
|
||||
{
|
||||
i = root(i); j = root(j);
|
||||
s.push({{i, par[i]}, {j, par[j]}});
|
||||
|
||||
if(i == j) return false;
|
||||
|
||||
if(-par[i] < -par[j]) swap(i, j);
|
||||
|
||||
par[i] += par[j]; par[j] = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void unjoin()
|
||||
{
|
||||
assert(!s.empty());
|
||||
auto [i, j] = s.top(); s.pop();
|
||||
|
||||
par[i.fi] = i.se;
|
||||
par[j.fi] = j.se;
|
||||
}
|
||||
};
|
||||
|
||||
struct dsu_pf : public dsu_pb
|
||||
{
|
||||
vector<pair<bool, pii> > st; // fi==0 -> B type, fi==1 -> A type
|
||||
vector<pair<bool, pii> > tmp[2];
|
||||
|
||||
int A=0, B=0;
|
||||
|
||||
dsu_pf(int N):dsu_pb(N){}
|
||||
|
||||
bool join(int i, int j)
|
||||
{
|
||||
st.pb({0, {i, j}}); B++;
|
||||
return dsu_pb::join(i, j);
|
||||
}
|
||||
void pop_front()
|
||||
{
|
||||
assert(!st.empty());
|
||||
if(A == 0)
|
||||
{
|
||||
forr(i, B) unjoin();
|
||||
|
||||
A = B; B = 0;
|
||||
reverse(all(st));
|
||||
for(auto &[b, p]:st) b = 1, dsu_pb::join(p.fi, p.se);
|
||||
}
|
||||
else if(st.back().fi == false)
|
||||
{
|
||||
tmp[st.back().fi].pb(st.back()); st.pop_back();
|
||||
unjoin();
|
||||
|
||||
while(tmp[0].size() != tmp[1].size() and (unsigned) A != tmp[1].size())
|
||||
{
|
||||
tmp[st.back().fi].pb(st.back());
|
||||
st.pop_back();
|
||||
unjoin();
|
||||
}
|
||||
|
||||
for(auto i:{0, 1}) reverse(all(tmp[i]));
|
||||
for(auto i:{0, 1}) for(auto v:tmp[i])
|
||||
st.pb(v), dsu_pb::join(v.se.fi, v.se.se);
|
||||
|
||||
tmp[0].clear(); tmp[1].clear();
|
||||
}
|
||||
|
||||
A--; st.pop_back();
|
||||
unjoin();
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user