teamnote default

This commit is contained in:
2026-06-03 09:20:51 +09:00
commit f50ed902fe
65 changed files with 6033 additions and 0 deletions

9
source/DS/Fenwick.cpp Normal file
View File

@@ -0,0 +1,9 @@
ll tree[N];
void update(int i,ll x) {
while(i < N) tree[i] += x, i += i&-i;
}
int query(int i) {
ll s = 0;
while(i) s += tree[i], i -= i&-i;
return s;
}

47
source/DS/LiChaoTree.cpp Normal file
View File

@@ -0,0 +1,47 @@
const ll L = 1e9+7, inf = 2*L*L+7;
struct Line {
ll a, b;
ll operator()(ll x){return a*x+b;}
Line():a(0),b(-inf){}
Line(ll a, ll b):a(a), b(b){}
};
struct Node {ll l, r; Line v; Node():l(-1), r(-1), v(){}};
using LiChao = vector<Node>;
// add Line v in [l, r]
void update(LiChao& seg, Line v, ll l, ll r, ll s=-L, ll e=L, ll i=0) {
if(e < l or r < s) return;
if(s == e) { seg[i].v = (seg[i].v(s) > v(s))?seg[i].v:v; return; }
ll mid=(s+e)>>1;
if(l <= s && e <= r) {
Line A = seg[i].v, B = v; if(A(s) < B(s)) swap(A, B);
if(A(e) >= B(e)) seg[i].v = A;
else if(A(mid) >= B(mid)) {
seg[i].v = A;
if(seg[i].r == -1) seg[i].r = seg.size(), seg.pb(Node());
update(seg, B, mid+1, e, mid+1, e, seg[i].r);
}
else {
seg[i].v = B;
if(seg[i].l == -1) seg[i].l = seg.size(), seg.pb(Node());
update(seg, A, s, mid, s, mid, seg[i].l);
}
return;
}
if(seg[i].l == -1) seg[i].l = seg.size(), seg.pb(Node());
if(seg[i].r == -1) seg[i].r = seg.size(), seg.pb(Node());
update(seg, v, l, r, s, mid, seg[i].l);
update(seg, v, l, r, mid+1, e, seg[i].r);
}
// query max_{l_i <= x <= r_i} (a_i*x + b_i)
ll query(LiChao& seg, ll x, ll s=-L, ll e=L, ll i=0) {
if(i == -1 or x < s or e < x) return -inf;
if(s == e) return seg[i].v(x);
ll mid = (s+e)>>1;
return max({query(seg, x, s, mid, seg[i].l), query(seg, x, mid+1, e, seg[i].r), seg[i].v(x)});
}
// LiChao seg(1, Node());
// update(seg, {a, b}, l, r);
// ll v = query(seg, x);

37
source/DS/PBDS.cpp Normal file
View File

@@ -0,0 +1,37 @@
#include <bits/stdc++.h>
#include <ext/rope>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace __gnu_cxx;
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
/////////////////////////////////////////////////////////////
// greater_equal <- ordered_multiset / greater <- ordered_multiset
#define oset_greater tree<ll, null_type, greater_equal<ll>, rb_tree_tag, tree_order_statistics_node_update>
#define oset_less tree<ll, null_type, less_equal<ll>, rb_tree_tag, tree_order_statistics_node_update>
void oset_m_erase(ordered_set_greater &OS, ll val){
int index = OS.order_of_key(val);
oset_greater::iterator it = OS.find_by_order(index);
if(it != OS.end() && *it == val) OS.erase(it);
}
/////////////////////////////////////////////////////////////
rope<ll> r;
r.insert(r.size() - t, i); //r.size()-t번째 자리에 i를 삽입
r.substr(a, b - a + 1) // a부터 (b-a+1)개 만큼을 잘라낸다. 즉, [a, b] 선택

86
source/DS/STBeats.cpp Normal file
View File

@@ -0,0 +1,86 @@
const int inf = 1e9+7;
#define data _data
struct data{
ll mx, mx_cnt, mx2, sum;
constexpr data(ll m):mx(m), mx_cnt(1), mx2(-inf), sum(m) {}
constexpr data(ll mx, ll mx_cnt, ll mx2, ll sum):mx(mx), mx_cnt(mx_cnt), mx2(mx2), sum(sum) {}
};
data join(data A, data B)
{
if(A.mx == B.mx)
return {A.mx, A.mx_cnt+B.mx_cnt, max(A.mx2, B.mx2), A.sum+B.sum};
if(A.mx < B.mx) swap(A, B);
return {A.mx, A.mx_cnt, max(A.mx2, B.mx), A.sum+B.sum};
}
using Seg = vector<data>;
void init(Seg& seg, int i, int s, int e, ll* A)
{
if(s == e) { seg[i] = A[s]; return; }
int mid = (s+e)/2;
init(seg, i*2, s, mid, A); init(seg, i*2+1, mid+1, e, A);
seg[i] = join(seg[i*2], seg[i*2+1]);
}
void prop(Seg& seg, int i, int s, int e)
{
if(s == e) return;
for(auto t : {i*2, i*2+1}) {
if(seg[t].mx > seg[i].mx) {
seg[t].sum -= seg[t].mx_cnt * (seg[t].mx - seg[i].mx);
seg[t].mx = seg[i].mx;
}
}
}
void update(Seg& seg, int i, int s, int e, int a, int b, ll v)
{
prop(seg, i, s, e);
if(e<a || b<s || seg[i].mx <= v) return;
if(a<=s && e<=b && seg[i].mx2 < v)
{
seg[i].sum -= seg[i].mx_cnt * (seg[i].mx - v);
seg[i].mx = v;
prop(seg, i, s, e);
return;
}
int mid = (s+e)/2;
update(seg, i*2, s, mid, a, b, v);
update(seg, i*2+1, mid+1, e, a, b, v);
seg[i] = join(seg[i*2], seg[i*2+1]);
}
ll querymax(Seg& seg, int i, int s, int e, int a, int b)
{
prop(seg, i, s, e);
if(e<a || b<s) return -inf;
if(a<=s && e<=b) return seg[i].mx;
int mid = (s+e)/2;
return max(querymax(seg, i*2, s, mid, a, b), querymax(seg, i*2+1, mid+1, e, a, b));
}
ll querysum(Seg& seg, int i, int s, int e, int a, int b)
{
prop(seg, i, s, e);
if(e<a || b<s) return 0;
if(a<=s && e<=b) return seg[i].sum;
int mid = (s+e)/2;
return querysum(seg, i*2, s, mid, a, b)+querysum(seg, i*2+1, mid+1, e, a, b);
}
const int N = 1e6+7;
ll A[N];
getint(n); get A;
Seg s(4*n, 0); init(s, 1, 1, n, A);
// A[i] = min(A[i], x) for l <= i <= r
update(s, 1, 1, n, l, r, x);
// summation query, max query
querysum(s, 1, 1, n, l, r), querymax(s, 1, 1, n, l, r);

36
source/DS/SegmentTree.cpp Normal file
View File

@@ -0,0 +1,36 @@
struct Data{
ll sum, lazy;
constexpr Data(ll m):sum(m), lazy(){}
constexpr Data(ll sum, ll lazy):sum(sum), lazy(lazy){}
};
Data join(Data A, Data B) {return A.sum+B.sum;}
using Seg = vector<Data>;
void init(Seg& seg, int i, int s, int e, ll *A) {
if(s == e) {seg[i] = A[s]; return;}
int mid = (s+e)>>1;
init(seg, i*2, s, mid, A); init(seg, i*2+1, mid+1, e, A);
seg[i] = join(seg[i*2], seg[i*2+1]);
}
void prop(Seg& seg, int i, int s, int e) {
seg[i].sum += seg[i].lazy * (e-s+1);
if(s != e) for(auto t:{i*2, i*2+1}) seg[t].lazy += seg[i].lazy;
seg[i].lazy = 0;
}
void update(Seg& seg, int i, int s, int e, int a, int b, ll v) {
prop(seg, i, s, e);
if(e<a||b<s) return;
if(a<=s&&e<=b) {seg[i].lazy+=v; prop(seg, i, s, e); return;}
int mid = (s+e)>>1;
update(seg, i*2, s, mid, a, b, v); update(seg, i*2+1, mid+1, e, a, b, v);
seg[i] = join(seg[i*2], seg[i*2+1]);
}
ll query(Seg& seg, int i, int s, int e, int a, int b) {
prop(seg, i, s, e);
if(e<a||b<s) return 0;
if(a<=s&&e<=b) return seg[i].sum;
int mid = (s+e)>>1;
return query(seg, i*2, s, mid, a, b) + query(seg, i*2+1, mid+1, e, a, b);
}

View File

@@ -0,0 +1,160 @@
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>;

127
source/DS/SplayTree.cpp Normal file
View File

@@ -0,0 +1,127 @@
struct Node
{
Node *p, *l, *r; int cnt; ll val;
ll m, M, sum; ll lazy; bool flip, dum;
Node(ll val, bool dum = false): p(0), l(0), r(0), cnt(1), val(val), m(val), M(val), sum(val), lazy(0), flip(0), dum(dum){}
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;
// 자기보다 더 높은 노드를 루트로 하는 SplayTree를 조작하는 경우, 하위 SplayTree는 unvalid된다.
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(ll val, bool dum = false){
if(!root) return root = new Node(val, dum);
Node *now = root; while(now->r) now = now->r;
Node* ret = now->r = new Node(val, dum);
now->r->p = now; return splay(ret), ret;
}
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();
}
return splay(now), now;
}
// s-1, e+1번째 노드가 항상 존재해야 한다.
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(){p_vals(root, 0, false);}
void p_vals(Node* node, ll lz, bool flip){
lz += node->lazy; flip ^= node->flip;
if(!flip){
if(node->l) p_vals(node->l, lz, flip);
if(!node->dum) printf("%lld ", node->val+lz);
if(node->r) p_vals(node->r, lz, flip);
}
else{
if(node->r) p_vals(node->r, lz, flip);
if(!node->dum) printf("%lld ", node->val+lz);
if(node->l) p_vals(node->l, lz, flip);
}
}
};
// SplayTree sp;
// fors(i, 0, n+1) arr[i] = sp.insert(i, i==0 or i == n+1);
// Node* node = sp.gather(l, r); sp.reverse(l, r);
// sp.find_kth(k); sp.splay(arr[k]);

60
source/DS/UF_QUndo.cpp Normal file
View File

@@ -0,0 +1,60 @@
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();
}
};