├── .gitignore ├── Code ├── 平衡树系列 │ ├── 替罪羊树 │ │ └── 替罪羊树.cpp │ ├── Splay │ │ ├── Splay(代码简化版).cpp │ │ └── Splay(普通平衡树).cpp │ ├── fhq Treap │ │ ├── fhq Treap(文艺平衡树).cpp │ │ └── fhq Treap(普通平衡树).cpp │ └── AVL树 │ │ └── AVL.cpp ├── 快速幂 │ └── 快速幂.cpp ├── 舞蹈链 │ ├── P4929 舞蹈链.cpp │ ├── P1787 数独.cpp │ └── DLX.h ├── 高斯消元 │ └── 高斯消元.cpp ├── dsu on tree │ └── dsu on tree(CF600E).cpp ├── 主席树系列 │ ├── 主席树 │ │ └── 主席树.cpp │ ├── 可持久化数组 │ │ └── 可持久化数组.cpp │ └── 可持久化并查集 │ │ └── 可持久化并查集.cpp ├── 矩阵模板 │ └── 模板+快速幂.cpp ├── 树链剖分 │ ├── 树链剖分求LCA.cpp │ └── 树链剖分.cpp ├── 线段树分裂合并 │ ├── P5494 【模板】线段树分裂.cpp │ ├── P4556 [Vani有约会]雨天的尾巴 【模板】线段树合并.cpp │ └── P2824 排序,AcWing3419 双向排序.cpp ├── 动态DP │ ├── LZUFeiMa_D.cpp │ └── 动态DP.cpp ├── 最短路径问题 │ └── Bellman-Ford │ │ ├── P3371 Bellman-Ford.cpp │ │ └── P3385 Bellman-Ford.cpp ├── 莫队 │ └── 小B的询问.cpp ├── 扫描线 │ └── 扫描线.cpp ├── 左偏树 │ └── 洛谷P3377 左偏树.cpp ├── 点分治 │ ├── 点分治.cpp │ └── 经典例题 洛谷P4178&&POJ1741 Tree.cpp └── Link Cut Tree │ └── Link Cut Tree.cpp ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode -------------------------------------------------------------------------------- /Code/平衡树系列/替罪羊树/替罪羊树.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StableAgOH/Codebase/HEAD/Code/平衡树系列/替罪羊树/替罪羊树.cpp -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bilibili 代码仓库 2 | 3 | B 站视频内的代码 4 | 5 | [bilibili 主页](https://space.bilibili.com/120174936) 6 | 7 | 视频中的PPT请加 QQ 群:940656404 8 | -------------------------------------------------------------------------------- /Code/快速幂/快速幂.cpp: -------------------------------------------------------------------------------- 1 | //€€₣版本 2 | #include 3 | using namespace std; 4 | int x, p, m, i, result; 5 | int main() 6 | { 7 | cin >> x >> p >> m; 8 | result = 1; 9 | while (p) 10 | { 11 | if (p % 2 == 1) 12 | result = result * x % m; 13 | p /= 2; 14 | x = x * x % m; 15 | } 16 | cout << result << endl; 17 | return 0; 18 | } 19 | //压行狂魔版本 20 | template 21 | T qpow(T a, T k, T m) 22 | { 23 | auto ans = a; 24 | for(k--;k>0;k>>=1,a*=a%m,a%=m) 25 | if(k&1) ans*=a%m,ans%=m; 26 | return ans%m; 27 | } 28 | -------------------------------------------------------------------------------- /Code/舞蹈链/P4929 舞蹈链.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | //========================================== 6 | #include "DLX.h" 7 | int main(int argc, char const *argv[]) 8 | { 9 | #ifdef LOCAL 10 | freopen("in.in", "r", stdin); 11 | freopen("out.out", "w", stdout); 12 | #endif 13 | clock_t c1 = clock(); 14 | //====================================== 15 | int n,m; 16 | cin>>n>>m; 17 | DLX solver(m); 18 | for(int i=1;i<=n;i++) 19 | { 20 | vector v; 21 | for(int j=1;j<=m;j++) 22 | { 23 | int tmp; 24 | cin>>tmp; 25 | if(tmp) v.push_back(j); 26 | } 27 | solver.addRow(i,v); 28 | } 29 | if(!solver.solve([](vector v){ 30 | for(auto i : v) cout< 2 | #include 3 | #include 4 | using namespace std; 5 | //========================================== 6 | #include 7 | #include "DLX.h" 8 | int sdk[11][11]; 9 | enum Task { Grid,Row,Col,Sub }; 10 | inline int encode(int x,int r,int c) 11 | { 12 | return x*9*9+(r-1)*9+c; 13 | } 14 | inline auto decode(int n) 15 | { 16 | n--; 17 | int x,r,c; 18 | c = n%9+1; n/=9; 19 | r = n%9+1; n/=9; 20 | x = n; 21 | return make_tuple(x,r,c); 22 | } 23 | int main(int argc, char const *argv[]) 24 | { 25 | #ifdef LOCAL 26 | freopen("in.in", "r", stdin); 27 | freopen("out.out", "w", stdout); 28 | #endif 29 | clock_t c1 = clock(); 30 | //====================================== 31 | DLX solver(4*9*9); 32 | for(int i=1;i<=9;i++) 33 | { 34 | for(int j=1;j<=9;j++) 35 | { 36 | int tmp; 37 | cin>>tmp; 38 | for(int k=1;k<=9;k++) 39 | { 40 | vector v; 41 | if(tmp&&tmp!=k) continue; 42 | v.push_back(encode(Grid,i,j)); 43 | v.push_back(encode(Row,i,k)); 44 | v.push_back(encode(Col,j,k)); 45 | int r = (i-1)/3; 46 | int c = (j-1)/3+1; 47 | v.push_back(encode(Sub,r*3+c,k)); 48 | solver.addRow(encode(k-1,i,j),v); 49 | } 50 | } 51 | } 52 | solver.solve([](vector v) { 53 | for(auto i : v) 54 | { 55 | int x,r,c; 56 | tie(x,r,c) = decode(i); 57 | sdk[r][c] = x+1; 58 | } 59 | for(int i=1;i<=9;i++) 60 | { 61 | for(int j=1;j<=9;j++) 62 | cout< 2 | #include 3 | #include 4 | using namespace std; 5 | //========================================== 6 | #include 7 | #include 8 | #include 9 | const int MAXN = 105; 10 | const double EPS = 1e-8; 11 | struct Matrix 12 | { 13 | int r,c; 14 | double ele[MAXN][MAXN]; 15 | Matrix(int r,int c):r(r),c(c) { memset(ele,0,sizeof(ele)); } 16 | double &operator()(int r,int c) { return ele[r][c]; } 17 | }; 18 | istream &operator>>(istream &is, Matrix &mat) 19 | { 20 | for (int i=0;i>mat(i,j); 23 | return is; 24 | } 25 | ostream &operator<<(ostream &os, Matrix &mat) 26 | { 27 | for(int i=0;i>n; 72 | static Matrix mat(n,n+1); 73 | cin>>mat; 74 | if(gauss(mat)) print(mat); 75 | else cout<<"No Solution"< 2 | #include 3 | const int maxn = 1e5+5; 4 | struct E 5 | { 6 | int to,next; 7 | }Edge[maxn<<1]; 8 | int tot,Head[maxn]; 9 | inline void AddEdge(int u,int v) 10 | { 11 | Edge[tot].to=v; 12 | Edge[tot].next=Head[u]; 13 | Head[u]=tot++; 14 | } 15 | int siz[maxn],son[maxn]; 16 | void dfs(int u,int f) //与重链剖分相同的写法找重儿子 17 | { 18 | siz[u]=1; 19 | for(int i=Head[u];~i;i=Edge[i].next) 20 | { 21 | int v = Edge[i].to; 22 | if(v==f) continue; 23 | dfs(v,u); 24 | siz[u]+=siz[v]; 25 | if(siz[v]>siz[son[u]]) 26 | son[u]=v; 27 | } 28 | } 29 | int col[maxn],cnt[maxn]; //col存放某结点的颜色,cnt存放某颜色在“当前”子树中的数量 30 | long long ans[maxn],sum; //ans是答案数组,sum用于累加计算出“当前”子树的答案 31 | int flag,maxc; //flag用于标记重儿子,maxc用于更新最大值 32 | //TODO 统计某结点及其所有轻儿子的贡献 33 | void count(int u,int f,int val) 34 | { 35 | cnt[col[u]]+=val;//val为正为负可以控制是增加贡献还是删除贡献 36 | if(cnt[col[u]]>maxc) //找最大值,基操吧 37 | { 38 | maxc=cnt[col[u]]; 39 | sum=col[u]; 40 | } 41 | else if(cnt[col[u]]==maxc) //这样做是因为如果两个颜色数量相同那都得算 42 | sum+=col[u]; 43 | for(int i=Head[u];~i;i=Edge[i].next) //排除被标记的重儿子,统计其它儿子子树信息 44 | { 45 | int v = Edge[i].to; 46 | if(v==f||v==flag) continue; //不能写if(v==f||v==son[u]) continue; 47 | count(v,u,val); 48 | } 49 | } 50 | //dsu on tree的板子 51 | void dfs(int u,int f,bool keep) 52 | { 53 | //* 第一步:搞轻儿子及其子树算其答案删贡献 54 | for(int i=Head[u];~i;i=Edge[i].next) 55 | { 56 | int v = Edge[i].to; 57 | if(v==f||v==son[u]) continue; 58 | dfs(v,u,false); 59 | } 60 | //* 第二步:搞重儿子及其子树算其答案不删贡献 61 | if(son[u]) 62 | { 63 | dfs(son[u],u,true); 64 | flag = son[u]; 65 | } 66 | //* 第三步:暴力统计u及其所有轻儿子的贡献合并到刚算出的重儿子信息里 67 | count(u,f,1); 68 | flag = 0; 69 | ans[u] = sum; 70 | //* 把需要删除贡献的删一删 71 | if(!keep) 72 | { 73 | count(u,f,-1); 74 | sum=maxc=0; //这是因为count函数中会改变这两个变量值 75 | } 76 | } 77 | int main() 78 | { 79 | #ifndef ONLINE_JUDGE 80 | freopen("in.in","r",stdin); 81 | freopen("out.out","w",stdout); 82 | #endif 83 | memset(Head,-1,sizeof(Head)); 84 | int n; 85 | scanf("%d",&n); 86 | for(int i=1;i<=n;i++) 87 | scanf("%d",col+i); 88 | for(int i=1,u,v;i 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | inline int getc() 10 | { 11 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 12 | } 13 | inline int read() 14 | { 15 | int ret = 0, f = 0; 16 | char ch = getc(); 17 | while (!isdigit(ch)) 18 | { 19 | if (ch == '-') 20 | f = 1; 21 | ch = getc(); 22 | } 23 | while (isdigit(ch)) 24 | { 25 | ret = ret * 10 + ch - 48; 26 | ch = getc(); 27 | } 28 | return f ? -ret : ret; 29 | } 30 | inline void flush() 31 | { 32 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 33 | } 34 | inline void print(int x) 35 | { 36 | if (p3 > 1 << 20) 37 | flush(); 38 | if (x < 0) 39 | buf2[++p3] = 45, x = -x; 40 | do 41 | { 42 | a[++p] = x % 10 + 48; 43 | } while (x /= 10); 44 | do 45 | { 46 | buf2[++p3] = a[p]; 47 | } while (--p); 48 | buf2[++p3] = hh; 49 | } 50 | } 51 | #define read() FastIO::read() 52 | #define print(x) FastIO::print(x) 53 | //====================================== 54 | #include 55 | #include 56 | const int maxn = 2e5+5; 57 | int a[maxn]; 58 | std::vector v; 59 | inline int getid(int x) { return lower_bound(v.begin(),v.end(),x)-v.begin()+1; } 60 | struct Node 61 | { 62 | int l,r,sum; 63 | }hjt[maxn*40]; 64 | int cnt,root[maxn]; 65 | void insert(int l,int r,int pre,int &now,int p) 66 | { 67 | hjt[++cnt]=hjt[pre]; 68 | now=cnt; 69 | hjt[now].sum++; 70 | if(l==r) return; 71 | int m = (l+r)>>1; //>>1 = /2 72 | if(p<=m) insert(l,m,hjt[pre].l,hjt[now].l,p); 73 | else insert(m+1,r,hjt[pre].r,hjt[now].r,p); 74 | } 75 | int query(int l,int r,int L,int R,int k) 76 | { 77 | if(l==r) return l; 78 | int m = (l+r)>>1; 79 | int tmp = hjt[hjt[R].l].sum-hjt[hjt[L].l].sum; 80 | if(k<=tmp) return query(l,m,hjt[L].l,hjt[R].l,k); 81 | else return query(m+1,r,hjt[L].r,hjt[R].r,k-tmp); 82 | } 83 | int main(int argc, char const *argv[]) 84 | { 85 | #ifndef ONLINE_JUDGE 86 | freopen("in.in", "r", stdin); 87 | freopen("out.out", "w", stdout); 88 | #endif 89 | clock_t c1 = clock(); 90 | //====================================== 91 | int n=read(),m=read(); 92 | for(int i=1;i<=n;i++) 93 | v.push_back(a[i]=read()); 94 | std::sort(v.begin(),v.end()); 95 | v.erase(std::unique(v.begin(),v.end()),v.end()); 96 | for(int i=1;i<=n;i++) 97 | insert(1,n,root[i-1],root[i],getid(a[i])); 98 | while(m--) 99 | { 100 | int l=read(),r=read(),k=read(); 101 | print(v[query(1,n,root[l-1],root[r],k)-1]); 102 | } 103 | //====================================== 104 | FastIO::flush(); 105 | std::cerr << "Time:" << clock() - c1 << std::endl; 106 | return 0; 107 | } 108 | 109 | -------------------------------------------------------------------------------- /Code/矩阵模板/模板+快速幂.cpp: -------------------------------------------------------------------------------- 1 | /* 2020-11-1:这个struct写的实在是太垃圾了, 2 | * 以后有时间再写一个吧, 3 | * 别学这个struct,真的垃圾 4 | */ 5 | #include 6 | #include 7 | using namespace std; 8 | template 9 | struct Matrix 10 | { 11 | int r, c; 12 | long long ele[row][col]; 13 | Matrix() { throw "Please set row and column!"; } 14 | Matrix(int a, int b) : r(a), c(b) { memset(ele, 0, sizeof(ele)); } 15 | long long &operator()(int a, int b) { return ele[a][b]; } 16 | Matrix &operator+=(Matrix oth) { return *this = *this + oth; } 17 | Matrix &operator-=(Matrix oth) { return *this = *this - oth; } 18 | Matrix &operator*=(Matrix oth) { return *this = *this * oth; } 19 | }; 20 | template 21 | Matrix operator+(Matrix m1, Matrix m2) 22 | { 23 | Matrix ret; 24 | for (int i = 0; i < m1.r; i++) 25 | for (int j = 0; j < m1.c; j++) 26 | ret(i, j) = m1(i, j) + m2(i, j); 27 | return ret; 28 | } 29 | template 30 | Matrix operator-(Matrix m1, Matrix m2) 31 | { 32 | Matrix ret; 33 | for (int i = 0; i < m1.r; i++) 34 | for (int j = 0; j < m1.c; j++) 35 | ret(i, j) = m1(i, j) + m2(i, j); 36 | return ret; 37 | } 38 | template 39 | Matrix operator*(Matrix m1, Matrix m2) //普通乘法 40 | { 41 | Matrix ret(m1.r, m2.c); 42 | for (int i = 0; i < m1.r; i++) 43 | for (int k = 0; k < m1.c; k++) 44 | for (int j = 0; j < m2.c; j++) 45 | ret(i, j) += m1(i, k) * m2(k, j); 46 | return ret; 47 | } 48 | template 49 | Matrix operator^(Matrix mat, long long k) //快速幂 50 | { 51 | Matrix ans = mat; 52 | for (k--; k; mat *= mat, k >>= 1) 53 | if (k & 1) 54 | ans *= mat; 55 | return ans; 56 | } 57 | template 58 | Matrix mulmod(Matrix m1, Matrix m2, int mod) //乘加取模 59 | { 60 | Matrix ret(m1.r, m2.c); 61 | for (int i = 0; i < m1.r; i++) 62 | for (int k = 0; k < m1.c; k++) 63 | for (int j = 0; j < m2.c; j++) 64 | ret(i, j) = (ret(i, j) + m1(i, k) * m2(k, j) % mod) % mod; 65 | return ret; 66 | } 67 | template 68 | Matrix qpowmod(Matrix mat, long long k, int mod) //快速幂取模 69 | { 70 | Matrix ans = mat; 71 | for (k--; k; mat = mulmod(mat, mat, mod), k >>= 1) 72 | if (k & 1) 73 | ans = mulmod(ans, mat, mod); 74 | return ans; 75 | } 76 | template 77 | ostream &operator<<(ostream &os, Matrix &mat) 78 | { 79 | for (int i = 0; i < mat.r; i++) 80 | { 81 | for (int j = 0; j < mat.c; j++) 82 | os << mat(i, j) << ' '; 83 | os << endl; 84 | } 85 | return os; 86 | } 87 | template 88 | istream &operator>>(istream &is, Matrix &mat) 89 | { 90 | for (int i = 0; i < mat.r; i++) 91 | for (int j = 0; j < mat.c; j++) 92 | is >> mat(i, j); 93 | return is; 94 | } 95 | const int maxn = 105; 96 | int main() 97 | { 98 | int n; 99 | long long k; 100 | const int p = 1e9 + 7; 101 | cin >> n >> k; 102 | Matrix mat(n, n); 103 | cin >> mat; 104 | auto tmp = qpowmod(mat, k, p); 105 | cout << tmp; 106 | return 0; 107 | } -------------------------------------------------------------------------------- /Code/主席树系列/可持久化数组/可持久化数组.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() {} 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | #define read FastIO::read 59 | #define print FastIO::print 60 | //====================================== 61 | const int maxn = 1e6+5; 62 | int a[maxn]; 63 | struct Node 64 | { 65 | int l,r,val; 66 | }hjt[maxn*40]; 67 | int cnt,root[maxn]; 68 | void build(int l,int r,int &now) 69 | { 70 | now=++cnt; 71 | if(l==r) 72 | { 73 | hjt[now].val=a[l]; 74 | return; 75 | } 76 | int m = (l+r)>>1; 77 | build(l,m,hjt[now].l); 78 | build(m+1,r,hjt[now].r); 79 | } 80 | void modify(int l,int r,int ver,int &now,int &pos,int &num) 81 | { 82 | hjt[now=++cnt]=hjt[ver]; 83 | if(l==r) 84 | { 85 | hjt[now].val=num; 86 | return; 87 | } 88 | int m = (l+r)>>1; 89 | if(pos<=m) modify(l,m,hjt[ver].l,hjt[now].l,pos,num); 90 | else modify(m+1,r,hjt[ver].r,hjt[now].r,pos,num); 91 | } 92 | int query(int l,int r,int now,int &pos) 93 | { 94 | if(l==r) return hjt[now].val; 95 | int m = (l+r)>>1; 96 | if(pos<=m) return query(l,m,hjt[now].l,pos); 97 | else return query(m+1,r,hjt[now].r,pos); 98 | } 99 | int main(int argc, char const *argv[]) 100 | { 101 | #ifndef ONLINE_JUDGE 102 | freopen("in.in", "r", stdin); 103 | freopen("out.out", "w", stdout); 104 | #endif 105 | clock_t c1 = clock(); 106 | //====================================== 107 | int n,m,ver,opt,x,y; 108 | read(n,m); 109 | for(int i=1;i<=n;i++) read(a[i]); 110 | build(1,n,root[0]); 111 | for(int i=1;i<=m;i++) 112 | { 113 | read(ver,opt); 114 | switch(opt) 115 | { 116 | case 1: 117 | read(x,y); 118 | modify(1,n,root[ver],root[i],x,y); 119 | break; 120 | case 2: 121 | read(x); 122 | print(query(1,n,root[ver],x)); 123 | root[i]=root[ver]; 124 | break; 125 | } 126 | } 127 | //====================================== 128 | FastIO::flush(); 129 | std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 130 | return 0; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /Code/树链剖分/树链剖分求LCA.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() {} 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | #define read FastIO::read 59 | #define print FastIO::print 60 | //====================================== 61 | const int maxn = 5e5+5; 62 | struct E 63 | { 64 | int to,next; 65 | }Edge[maxn*2]; 66 | int tot,Head[maxn]; 67 | inline void AddEdge(int u,int v) 68 | { 69 | Edge[tot].to=v,Edge[tot].next=Head[u],Head[u]=tot++; 70 | Edge[tot].to=u,Edge[tot].next=Head[v],Head[v]=tot++; 71 | } 72 | int fa[maxn],siz[maxn],son[maxn],dep[maxn]; 73 | void dfs1(int u,int f) 74 | { 75 | fa[u]=f,siz[u]=1,dep[u]=dep[f]+1; 76 | int maxson = -1; 77 | for(int i=Head[u];~i;i=Edge[i].next) 78 | { 79 | int &v = Edge[i].to; 80 | if(v==f) continue; 81 | dfs1(v,u); 82 | siz[u]+=siz[v]; 83 | if(siz[v]>maxson) 84 | maxson=siz[v],son[u]=v; 85 | } 86 | } 87 | int top[maxn]; 88 | void dfs2(int u,int t) 89 | { 90 | top[u]=t; 91 | if(!son[u]) return; 92 | dfs2(son[u],t); 93 | for(int i=Head[u];~i;i=Edge[i].next) 94 | { 95 | int &v = Edge[i].to; 96 | if(v==fa[u]||v==son[u]) continue; 97 | dfs2(v,v); 98 | } 99 | } 100 | #include 101 | int main(int argc, char const *argv[]) 102 | { 103 | #ifndef ONLINE_JUDGE 104 | freopen("in.in", "r", stdin); 105 | freopen("out.out", "w", stdout); 106 | #endif 107 | clock_t c1 = clock(); 108 | //====================================== 109 | memset(Head,-1,sizeof(Head)); 110 | int n,m,s; 111 | read(n,m,s); 112 | while(--n) 113 | { 114 | int u,v; 115 | read(u,v); 116 | AddEdge(u,v); 117 | } 118 | dfs1(s,s); 119 | dfs2(s,s); 120 | while(m--) 121 | { 122 | int u,v; 123 | read(u,v); 124 | while(top[u]!=top[v]) 125 | { 126 | if(dep[top[u]] 2 | #include 3 | #include 4 | using namespace std; 5 | //========================================== 6 | const int maxn = 2e5 + 5; 7 | typedef long long ll; 8 | struct Node 9 | { 10 | int l,r; 11 | ll val; 12 | }sgt[maxn*40]; //? 40 = 2*maxm*log2(maxn) 13 | int cnt,root[maxn]; 14 | inline void pushup(int k) { sgt[k].val = sgt[sgt[k].l].val + sgt[sgt[k].r].val; } 15 | void modify(int l,int r,int &k,int p,int x) // 单点修改:p位置的值加上x,空间复杂度O(logn) 16 | { 17 | if(!k) k=++cnt; // 如果到了NIL结点就新建一个 18 | sgt[k].val += x; // 单点修改的加法直接一条线上全部加上x即可 19 | if(l==r) return; 20 | int m = (l+r)>>1; 21 | if(p<=m) modify(l, m, sgt[k].l, p, x); // 在左子树 22 | else modify(m+1, r, sgt[k].r, p, x); // 在右子树 23 | } 24 | void merge(int &x,int y) // 把y结点的内容合并到x结点上,此写法不消耗空间 25 | { 26 | if(!(x&&y)) x|=y; // 如果二者有NULL结点 27 | else 28 | { 29 | sgt[x].val += sgt[y].val; // 维护加法,直接加就是了 30 | merge(sgt[x].l, sgt[y].l); // 递归合并两结点的左子树 31 | merge(sgt[x].r, sgt[y].r); // 递归合并两结点的右子树 32 | } 33 | } 34 | int split(int l,int r,int &k,int x,int y) // 从k中分离出[x,y]区间并返回新结点编号,空间复杂度O(2logn) 35 | { 36 | int n = ++cnt; 37 | if(x<=l&&y>=r) // 如果k结点维护的区间在[x,y]中 38 | { 39 | sgt[n] = sgt[k]; // 直接拿过来便是 40 | k = 0; // 置为NULL,断掉联系 41 | } 42 | else 43 | { 44 | int m = (l+r)>>1; 45 | if(x<=m) sgt[n].l = split(l, m, sgt[k].l, x, y); // 若左子树中有区间信息 46 | if(y>m) sgt[n].r = split(m+1, r, sgt[k].r, x, y); // 若右子树中有区间信息 47 | pushup(k); 48 | pushup(n); // 更改后记得更新值 49 | } 50 | return n; 51 | } 52 | ll query(int l,int r,int k,int x,int y) // 区间查询 53 | { 54 | if(x<=l&&y>=r) return sgt[k].val; 55 | int m = (l+r)>>1; 56 | ll sum = 0; 57 | if(x<=m) sum += query(l,m,sgt[k].l,x,y); 58 | if(y>m) sum += query(m+1,r,sgt[k].r,x,y); 59 | return sum; 60 | } 61 | ll query(int l,int r,int k,int kth) // 单点查询 62 | { 63 | if(l==r) return l; 64 | int m = (l+r)>>1; 65 | if(kth<=sgt[sgt[k].l].val) return query(l,m,sgt[k].l,kth); 66 | else return query(m+1,r,sgt[k].r,kth-sgt[sgt[k].l].val); 67 | } 68 | signed main(signed argc, char const *argv[]) 69 | { 70 | clock_t c1 = clock(); 71 | #ifdef LOCAL 72 | freopen("in.in", "r", stdin); 73 | freopen("out.out", "w", stdout); 74 | #endif 75 | //====================================== 76 | int n,m; 77 | cin>>n>>m; 78 | for(int i=1;i<=n;i++) 79 | { 80 | int x; 81 | cin>>x; 82 | modify(1,n,root[1],i,x); // 初始状态下值都为0,所以加x即为置为x 83 | } 84 | int last = 1; 85 | while(m--) 86 | { 87 | int opt,x,y,z; 88 | cin>>opt>>x>>y; 89 | switch(opt) 90 | { 91 | case 0: 92 | cin>>z; 93 | root[++last] = split(1, n, root[x], y, z); 94 | break; 95 | case 1: 96 | merge(root[x],root[y]); 97 | break; 98 | case 2: 99 | cin>>z; 100 | modify(1,n,root[x],z,y); 101 | break; 102 | case 3: 103 | cin>>z; 104 | cout<sgt[root[x]].val) cout<<-1< 2 | #include 3 | //! 此代码不吸氧必然会跑得很慢,建议搭配氧气使用 4 | class DLX 5 | { 6 | private: 7 | struct Node{ int l,r,u,d,row,col; }; 8 | std::vector dcl; //十字链表结点 9 | std::vector s,ans; //某列结点个数,答案栈 10 | bool ms; //是否多解 11 | std::function)> process; //在得到一个解后对答案进行处理的函数 12 | 13 | void remove(int col) //删除col列及col列中结点所在行中结点所在列 14 | { 15 | dcl[dcl[col].r].l = dcl[col].l; //断掉列首结点与其左右结点的关系 16 | dcl[dcl[col].l].r = dcl[col].r; 17 | for(int i=dcl[col].d;i!=col;i=dcl[i].d) //遍历col列所有结点 18 | { 19 | for(int j=dcl[i].r;j!=i;j=dcl[j].r) //遍历col列所有结点所在行的所有结点 20 | { 21 | dcl[dcl[j].d].u = dcl[j].u; //断掉该结点与其上下结点的关系 22 | dcl[dcl[j].u].d = dcl[j].d; //注意并没有断掉左右关系,这使得恢复操作变得简单 23 | s[dcl[j].col]--; //该结点所在列的结点个数减1 24 | } 25 | } 26 | } 27 | void restore(int col) //与remove相反 28 | { 29 | dcl[dcl[col].r].l = col; 30 | dcl[dcl[col].l].r = col; 31 | for(int i=dcl[col].d;i!=col;i=dcl[i].d) 32 | { 33 | for(int j=dcl[i].r;j!=i;j=dcl[j].r) 34 | { 35 | dcl[dcl[j].d].u = j; 36 | dcl[dcl[j].u].d = j; 37 | s[dcl[j].col]++; 38 | } 39 | } 40 | } 41 | bool dance() 42 | { 43 | int col = dcl[0].r; //Head右边的结点 44 | if(!col) return process(ans),true; //得到了一个解 45 | bool ret = false; //返回值 46 | for(int i=col;i;i=dcl[i].r) //寻找结点数量最小的列,加快求解速度 47 | if(s[i] col) //为十字链表增加一行,row为行编号,col中存放值为1的列的编号 76 | { 77 | int first = dcl.size(); //暂存行首结点 78 | for(int c : col) 79 | { 80 | int tmp = dcl.size(); //被push_back的结点的下标 81 | dcl.push_back( {tmp-1,tmp+1,dcl[c].u,c,row,c} ); 82 | dcl[c].u = dcl[dcl[c].u].d = tmp; //建立上下关系 83 | s[c]++; 84 | } 85 | dcl[dcl.size()-1].r = first; //循环链表 86 | dcl[first].l = dcl.size()-1; 87 | } 88 | bool solve(std::function)> fun)//传入一个用于处理每个解的答案的函数 89 | { 90 | process = fun; 91 | return dance(); 92 | } 93 | }; 94 | -------------------------------------------------------------------------------- /Code/动态DP/LZUFeiMa_D.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | clock_t c1; 5 | inline void exit() 6 | { 7 | #ifdef LOCAL 8 | cerr << "Time Used:" << clock() - c1 << "ms" << endl; 9 | #endif 10 | exit(0); 11 | } 12 | //========================================== 13 | #include 14 | #include 15 | const int maxn = 1e5+5; 16 | const int mod = 998244353; 17 | template 18 | struct Mat { int ele[row][col]; }; 19 | Mat<6,6> mpow[6][maxn]; 20 | template 21 | Mat operator*(const Mat &m1, const Mat &m2) 22 | { 23 | Mat matt; 24 | for(int i=0;i ident = {{ 32 | {1,0,0,0,0,0}, 33 | {0,1,0,0,0,0}, 34 | {0,0,1,0,0,0}, 35 | {0,0,0,1,0,0}, 36 | {0,0,0,0,1,0}, 37 | {0,0,0,0,0,1}, 38 | }}; 39 | Mat<6,6> M[] = {ident, ident, ident, ident, ident, ident, ident}; 40 | char getMat[130]; 41 | auto ___ = [](){ 42 | M[1].ele[0][5]=M[2].ele[1][0]=M[3].ele[2][1]=M[4].ele[3][2]=M[5].ele[4][3]=1; 43 | fill(begin(getMat), end(getMat), 6); 44 | getMat['F']=1; 45 | getMat['e']=2; 46 | getMat['i']=3; 47 | getMat['M']=4; 48 | getMat['a']=5; 49 | return 0.0; 50 | }(); 51 | char s[maxn]; 52 | struct Node 53 | { 54 | int l,r,f; 55 | Mat<6,6> val; 56 | }sgt[maxn<<2]; 57 | #define ls(k) (k<<1) 58 | #define rs(k) (k<<1|1) 59 | inline void pushup(int k) { sgt[k].val=sgt[rs(k)].val*sgt[ls(k)].val; } 60 | inline void pushdw(int k) 61 | { 62 | int f=sgt[k].f; sgt[k].f=0; 63 | sgt[ls(k)].f=sgt[rs(k)].f=f; 64 | if(f==6) sgt[ls(k)].val=sgt[rs(k)].val=ident; 65 | else 66 | { 67 | sgt[ls(k)].val=mpow[f][sgt[ls(k)].r-sgt[ls(k)].l+1]; 68 | sgt[rs(k)].val=mpow[f][sgt[rs(k)].r-sgt[rs(k)].l+1]; 69 | } 70 | } 71 | void build(int l,int r,int k=1) 72 | { 73 | sgt[k].l=l, sgt[k].r=r, sgt[k].f=0; 74 | if(l==r) sgt[k].val=M[(int)getMat[(int)s[l-1]]]; 75 | else 76 | { 77 | int m = (l+r)>>1; 78 | build(l,m,ls(k)); 79 | build(m+1,r,rs(k)); 80 | pushup(k); 81 | } 82 | } 83 | void modify(int x,int y,int z,int k=1) 84 | { 85 | int l=sgt[k].l, r=sgt[k].r; 86 | if(x<=l&&y>=r) 87 | { 88 | sgt[k].f=z; 89 | if(z==6) sgt[k].val=ident; 90 | else sgt[k].val=mpow[z][r-l+1]; 91 | return; 92 | } 93 | if(sgt[k].f) pushdw(k); 94 | int m = (l+r)>>1; 95 | if(x<=m) modify(x,y,z,ls(k)); 96 | if(y>m) modify(x,y,z,rs(k)); 97 | pushup(k); 98 | } 99 | auto query(int x,int y,int k=1) 100 | { 101 | int l=sgt[k].l, r=sgt[k].r; 102 | if(x<=l&&y>=r) return sgt[k].val; 103 | if(sgt[k].f) pushdw(k); 104 | int m = (l+r)>>1; 105 | auto ret = ident; 106 | if(x<=m) ret = ret*query(x,y,ls(k)); 107 | if(y>m) ret = ret*query(x,y,rs(k)); 108 | return ret; 109 | } 110 | signed main(signed argc, char const *argv[]) 111 | { 112 | #ifdef LOCAL 113 | freopen("in.in", "r", stdin); 114 | freopen("out.out", "w", stdout); 115 | #endif 116 | c1 = clock(); 117 | ios::sync_with_stdio(false); 118 | cin.tie(nullptr); 119 | cout.tie(nullptr); 120 | //====================================== 121 | for(int i=1;i<=5;i++) mpow[i][0]=ident; 122 | for(int i=1;i<=5;i++) 123 | for(int j=1;j<=100001;j++) 124 | mpow[i][j]=mpow[i][j-1]*M[i]; 125 | int t; cin>>t; 126 | while(t--) 127 | { 128 | int n,q; cin>>n>>q>>s; 129 | build(1,n); 130 | while(q--) 131 | { 132 | int l,r; char c; 133 | cin>>l>>r>>c; 134 | modify(l,r,getMat[(int)c]); 135 | cout< 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh1 = '\n', hh2 = ' '; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() { buf2[p3] = hh1; } 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh2; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | using FastIO::print; 59 | using FastIO::read; 60 | //====================================== 61 | const int maxn = 1e4+5; 62 | const int maxm = 5e5+5; 63 | struct E 64 | { 65 | int u,v,w; 66 | }Edge[maxm]; 67 | long long dis[maxn]; 68 | #include 69 | int main(int argc, char const *argv[]) 70 | { 71 | #ifndef ONLINE_JUDGE 72 | freopen("in.in", "r", stdin); 73 | freopen("out.out", "w", stdout); 74 | #endif 75 | clock_t c1 = clock(); 76 | //====================================== 77 | int n,m,s; 78 | read(n,m,s); 79 | for(int i=0;i .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 116 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 117 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 118 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 119 | */ -------------------------------------------------------------------------------- /Code/线段树分裂合并/P4556 [Vani有约会]雨天的尾巴 【模板】线段树合并.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | //========================================== 6 | #include 7 | const int maxn = 1e5 + 5; 8 | typedef pair pii; // first元素存放救济粮数量,second存放该救济粮类型号 9 | struct Node 10 | { 11 | int l,r; 12 | pii val; 13 | }sgt[70*maxn]; //? 70 = 4*maxm*log2(maxn) 14 | int cnt, root[maxn]; 15 | pii& max(pii& x, pii& y) // 因为要取类型号较小的所以无法直接使用max比较 16 | { 17 | if(x.first>y.first) return x; 18 | else if(x.first==y.first) return x.secondmaxsize) 43 | { 44 | son[u]=v; 45 | maxsize = siz[v]; 46 | } 47 | } 48 | } 49 | int top[maxn]; 50 | void dfs2(int u,int t) 51 | { 52 | top[u]=t; 53 | if(son[u]) dfs2(son[u], t); 54 | for(int i=Head[u];~i;i=Edge[i].next) 55 | { 56 | int v = Edge[i].v; 57 | if(v==fa[u]||v==son[u]) continue; 58 | dfs2(v, v); 59 | } 60 | } 61 | int lca(int x,int y) 62 | { 63 | while(top[x]!=top[y]) 64 | { 65 | if(dep[top[x]]>1; 81 | if(p<=m) modify(l, m, sgt[k].l, p, x); 82 | else modify(m+1, r, sgt[k].r, p, x); 83 | pushup(k); 84 | } 85 | void merge(int &x,int y,int l=1,int r=maxn) // 此处的maxn其实是maxk,l与r用于方便判断是否到了叶子结点 86 | { 87 | if(!(x&&y)) 88 | x|=y; 89 | else if(l==r) 90 | sgt[x].val.first += sgt[y].val.first; // 到叶子结点时处理有可能发生的同类型救济粮之间的数量叠加 91 | else 92 | { 93 | int m = (l+r)>>1; 94 | merge(sgt[x].l, sgt[y].l, l, m); 95 | merge(sgt[x].r, sgt[y].r, m+1, r); 96 | pushup(x); 97 | } 98 | } 99 | int ans[maxn]; 100 | void dfs(int u) // dfs处理树上差分 101 | { 102 | for(int i=Head[u];~i;i=Edge[i].next) 103 | { 104 | int v = Edge[i].v; 105 | if(v==fa[u]) continue; 106 | dfs(v); // 头递归 107 | merge(root[u], root[v]); // 合并上所有的儿子结点 108 | } 109 | if(sgt[root[u]].val.first) // 若数量不为0,那么second即为u结点数量最多的救济粮 110 | ans[u]=sgt[root[u]].val.second; 111 | } 112 | #include 113 | signed main(signed argc, char const *argv[]) 114 | { 115 | clock_t c1 = clock(); 116 | #ifdef LOCAL 117 | freopen("in.in", "r", stdin); 118 | freopen("out.out", "w", stdout); 119 | #endif 120 | //====================================== 121 | memset(Head, -1, sizeof(Head)); 122 | int n,m; 123 | cin>>n>>m; 124 | for(int i=1;i>u>>v; 128 | AddEdge(u,v); 129 | AddEdge(v,u); 130 | } 131 | dfs1(1, 0); 132 | dfs2(1, 0); 133 | while(m--) 134 | { 135 | int x,y,z; 136 | cin>>x>>y>>z; 137 | // 以下为树上差分基操 138 | modify(1, maxn, root[x], z, 1); // x结点加上z救济粮标记 139 | modify(1, maxn, root[y], z, 1); // y结点加上z救济粮标记 140 | modify(1, maxn, root[lca(x,y)], z, -1); // lca(x,y)结点加上-z救济粮标记 141 | modify(1, maxn, root[fa[lca(x,y)]], z, -1); // fa[lca(x,y)]结点加上-z救济粮标记 142 | } 143 | dfs(1); // 差分统计 144 | for(int i=1;i<=n;i++) cout< 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh1 = '\n', hh2 = ' '; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() { buf2[p3] = hh1; } 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh2; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | using FastIO::print; 59 | using FastIO::read; 60 | //====================================== 61 | #include 62 | #include 63 | const int maxn = 5e4+5; 64 | int a[maxn],pos[maxn],cnt[maxn]; 65 | long long ans[maxn]; 66 | long long res; 67 | struct Q 68 | { 69 | int l,r,k; 70 | }q[maxn]; 71 | void Add(int n) { cnt[a[n]]++; res+=cnt[a[n]]*cnt[a[n]]-(cnt[a[n]]-1)*(cnt[a[n]]-1); } 72 | void Sub(int n) { cnt[a[n]]--; res-=(cnt[a[n]]+1)*(cnt[a[n]]+1)-cnt[a[n]]*cnt[a[n]]; } 73 | int main(int argc, char const *argv[]) 74 | { 75 | #ifndef ONLINE_JUDGE 76 | freopen("in.in", "r", stdin); 77 | freopen("out.out", "w", stdout); 78 | #endif 79 | clock_t c1 = clock(); 80 | //====================================== 81 | int n,m,k; 82 | read(n,m,k); 83 | int siz = sqrt(n); 84 | for(int i=1;i<=n;i++) 85 | { 86 | read(a[i]); 87 | pos[i]=i/siz; 88 | } 89 | for(int i=0;ir) Add(++r); 102 | while(q[i].l>l) Sub(l++); 103 | while(q[i].r .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 125 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 126 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 127 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 128 | */ -------------------------------------------------------------------------------- /Code/平衡树系列/Splay/Splay(代码简化版).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | //========================================== 5 | const int maxn = 1e5 + 5; 6 | struct Node 7 | { 8 | int fa, ch[2], val, size; //ch[0]是左儿子,ch[1]是右儿子 9 | } spl[maxn]; 10 | int cnt, root; 11 | inline void update(int x) 12 | { 13 | spl[x].size = spl[spl[x].ch[0]].size + spl[spl[x].ch[1]].size + 1; 14 | } 15 | inline bool ident(int x, int f) { return spl[f].ch[1] == x; } //查询父子关系 16 | inline void connect(int x, int f, int s) //建立父子关系 17 | { 18 | spl[f].ch[s] = x; 19 | spl[x].fa = f; 20 | } 21 | void rotate(int x) //合二为一的旋转 22 | { 23 | int f = spl[x].fa, ff = spl[f].fa, k = ident(x, f); 24 | connect(spl[x].ch[k ^ 1], f, k); //三次建立父子关系 25 | connect(x, ff, ident(f, ff)); 26 | connect(f, x, k ^ 1); 27 | update(f), update(x); //别忘了更新大小信息 28 | } 29 | void splaying(int x, int top) //代表把x转到top的儿子,top为0则转到根结点 30 | { 31 | if (!top) 32 | root = x; 33 | while (spl[x].fa != top) 34 | { 35 | int f = spl[x].fa, ff = spl[f].fa; 36 | if (ff != top) 37 | ident(f, ff) ^ ident(x, f) ? rotate(x) : rotate(f); 38 | rotate(x); //最后一次都是旋转x 39 | } 40 | } 41 | void newnode(int &now, int fa, int val) //新建节点,要注意fa指针的初始化 42 | { 43 | spl[now = ++cnt].val = val; 44 | spl[cnt].fa = fa; 45 | spl[cnt].size = 1; 46 | } 47 | void delnode(int x) //删除结点,要注意fa指针的维护 48 | { 49 | splaying(x, 0); 50 | if (spl[x].ch[1]) 51 | { 52 | int p = spl[x].ch[1]; 53 | while (spl[p].ch[0]) 54 | p = spl[p].ch[0]; 55 | splaying(p, x); 56 | connect(spl[x].ch[0], p, 0); 57 | root = p; 58 | spl[p].fa = 0; 59 | update(root); 60 | } 61 | else 62 | root = spl[x].ch[0], spl[root].fa = 0; 63 | } 64 | void ins(int val, int &now = root, int fa = 0) //递归式,要传fa指针 65 | { 66 | if (!now) 67 | newnode(now, fa, val), splaying(now, 0); 68 | else if (val < spl[now].val) 69 | ins(val, spl[now].ch[0], now); 70 | else 71 | ins(val, spl[now].ch[1], now); 72 | } 73 | void del(int val, int now = root) //同上 74 | { 75 | if (val == spl[now].val) 76 | delnode(now); 77 | else if (val < spl[now].val) 78 | del(val, spl[now].ch[0]); 79 | else 80 | del(val, spl[now].ch[1]); 81 | } 82 | int getrank(int val) 83 | { 84 | int now = root, rank = 1, pre = 0; 85 | while (now) 86 | { 87 | if (val <= spl[now].val) 88 | { 89 | pre = now; 90 | now = spl[now].ch[0]; 91 | } 92 | else 93 | { 94 | rank += spl[spl[now].ch[0]].size + 1; 95 | now = spl[now].ch[1]; 96 | } 97 | } 98 | if (pre) 99 | splaying(pre, 0); 100 | return rank; 101 | } 102 | int getnum(int rank) 103 | { 104 | int now = root; 105 | while (now) 106 | { 107 | if (spl[spl[now].ch[0]].size + 1 == rank) 108 | { 109 | splaying(now, 0); 110 | break; 111 | } 112 | else if (spl[spl[now].ch[0]].size >= rank) 113 | now = spl[now].ch[0]; 114 | else 115 | { 116 | rank -= spl[spl[now].ch[0]].size + 1; 117 | now = spl[now].ch[1]; 118 | } 119 | } 120 | return spl[now].val; 121 | } 122 | signed main(signed argc, char const *argv[]) 123 | { 124 | clock_t c1 = clock(); 125 | #ifdef LOCAL 126 | freopen("in.in", "r", stdin); 127 | freopen("out.out", "w", stdout); 128 | #endif 129 | ios::sync_with_stdio(false); 130 | cin.tie(nullptr); 131 | //====================================== 132 | int t; 133 | cin >> t; 134 | while (t--) 135 | { 136 | int opt, x; 137 | cin >> opt >> x; 138 | switch (opt) 139 | { 140 | case 1: 141 | ins(x); 142 | break; 143 | case 2: 144 | del(x); 145 | break; 146 | case 3: 147 | cout << getrank(x) << '\n'; 148 | break; 149 | case 4: 150 | cout << getnum(x) << '\n'; 151 | break; 152 | case 5: 153 | cout << getnum(getrank(x) - 1) << '\n'; 154 | break; 155 | case 6: 156 | cout << getnum(getrank(x + 1)) << '\n'; 157 | break; 158 | } 159 | } 160 | //====================================== 161 | #ifdef LOCAL 162 | end: 163 | cerr << "Time Used:" << clock() - c1 << "ms" << endl; 164 | #endif 165 | return 0; 166 | } -------------------------------------------------------------------------------- /Code/主席树系列/可持久化并查集/可持久化并查集.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() {} 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | #define read FastIO::read 59 | #define print FastIO::print 60 | //====================================== 61 | const int maxn = 2e5+5; 62 | int n; 63 | struct Node 64 | { 65 | int l,r,val; 66 | }hjt[maxn*40*2]; 67 | int cnt,rootfa[maxn],rootdep[maxn],tot; 68 | void build(int l,int r,int &now) 69 | { 70 | now = ++cnt; 71 | if(l==r) 72 | { 73 | hjt[now].val=++tot; 74 | return; 75 | } 76 | int m = (l+r)>>1; 77 | build(l,m,hjt[now].l); 78 | build(m+1,r,hjt[now].r); 79 | } 80 | void modify(int l,int r,int ver,int &now,int pos,int val) 81 | { 82 | hjt[now=++cnt]=hjt[ver]; 83 | if(l==r) 84 | { 85 | hjt[now].val=val; 86 | return; 87 | } 88 | int m = (l+r)>>1; 89 | if(pos<=m) modify(l,m,hjt[ver].l,hjt[now].l,pos,val); 90 | else modify(m+1,r,hjt[ver].r,hjt[now].r,pos,val); 91 | } 92 | int query(int l,int r,int now,int pos) 93 | { 94 | if(l==r) return hjt[now].val; 95 | int m = (l+r)>>1; 96 | if(pos<=m) return query(l,m,hjt[now].l,pos); 97 | else return query(m+1,r,hjt[now].r,pos); 98 | } 99 | int find(int ver,int x) 100 | { 101 | int fx = query(1,n,rootfa[ver],x); 102 | return fx==x?x:find(ver,fx); 103 | } 104 | void merge(int ver,int x,int y) 105 | { 106 | x = find(ver-1,x); //ver-1 107 | y = find(ver-1,y); 108 | if(x==y) 109 | { 110 | rootfa[ver]=rootfa[ver-1]; 111 | rootdep[ver]=rootdep[ver-1]; 112 | } 113 | else 114 | { 115 | int depx = query(1,n,rootdep[ver-1],x); 116 | int depy = query(1,n,rootdep[ver-1],y); 117 | if(depxdepy) 123 | { 124 | modify(1,n,rootfa[ver-1],rootfa[ver],y,x); 125 | rootdep[ver]=rootdep[ver-1]; 126 | } 127 | else 128 | { 129 | modify(1,n,rootfa[ver-1],rootfa[ver],x,y); 130 | modify(1,n,rootdep[ver-1],rootdep[ver],y,depy+1); 131 | } 132 | } 133 | } 134 | int main(int argc, char const *argv[]) 135 | { 136 | #ifndef ONLINE_JUDGE 137 | freopen("in.in", "r", stdin); 138 | freopen("out.out", "w", stdout); 139 | #endif 140 | clock_t c1 = clock(); 141 | //====================================== 142 | int m; 143 | read(n,m); 144 | build(1,n,rootfa[0]); 145 | for(int ver=1;ver<=m;ver++) 146 | { 147 | int opt,x,y; 148 | read(opt); 149 | switch(opt) 150 | { 151 | case 1: 152 | read(x,y); 153 | merge(ver,x,y); 154 | break; 155 | case 2: 156 | read(x); 157 | rootfa[ver]=rootfa[x]; 158 | rootdep[ver]=rootdep[x]; 159 | break; 160 | case 3: 161 | read(x,y); 162 | rootfa[ver]=rootfa[ver-1]; 163 | rootdep[ver]=rootdep[ver-1]; 164 | int fx = find(ver,x); 165 | int fy = find(ver,y); 166 | print(fx==fy?1:0); 167 | break; 168 | } 169 | } 170 | //====================================== 171 | FastIO::flush(); 172 | std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 173 | return 0; 174 | } 175 | 176 | -------------------------------------------------------------------------------- /Code/线段树分裂合并/P2824 排序,AcWing3419 双向排序.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | //========================================== 6 | #include 7 | #include 8 | #include 9 | #include 10 | const int maxn = 1e5 + 5; 11 | struct Node 12 | { 13 | int ch[2],val; // 儿子用数组来存放与Splay有异曲同工之用途 14 | }sgt[70*maxn]; 15 | int cnt; 16 | inline int& ls(int k) { return sgt[k].ch[0]; } 17 | inline int& rs(int k) { return sgt[k].ch[1]; } 18 | int modify(int l,int r,int p) // 单点修改,固定修改p位置为1 19 | { 20 | int n = ++cnt; 21 | sgt[n].val=1; 22 | if(l!=r) 23 | { 24 | int m = (l+r)>>1; 25 | if(p<=m) ls(n) = modify(l, m, p); 26 | else rs(n) = modify(m+1, r, p); 27 | } 28 | return n; 29 | } 30 | void merge(int &x, int y) // 经典merge,略 31 | { 32 | if(!x||!y) x|=y; 33 | else 34 | { 35 | sgt[x].val += sgt[y].val; 36 | merge(ls(x), ls(y)); 37 | merge(rs(x), rs(y)); 38 | } 39 | } 40 | int split(int k, int kth, bool rev) // 把前kth个数字之外的部分分裂出去并返回结点编号 41 | { 42 | if(sgt[k].val == kth) return 0; // 如果不够kth个无法分裂(不会出现<的情况所以==相当于<=) 43 | int n = ++cnt; 44 | sgt[n].val = sgt[k].val-kth; // 分裂出去的部分的数量为总数减kth个 45 | sgt[k].val = kth; // 剩下kth个 46 | int val = sgt[sgt[k].ch[rev]].val; // 靠前子树值,如果正序那么就是判断左子树数字数量,如果倒序那么就是判断右子树数字数量 47 | if(val>=kth) // 如果在靠前子树 48 | { 49 | sgt[n].ch[rev] = split(sgt[k].ch[rev], kth, rev); // 分裂靠前子树 50 | sgt[n].ch[!rev] = sgt[k].ch[!rev]; // 靠前子树只剩kth个,靠后子树自然是要归给新结点(新结点是剩余部分嘛) 51 | sgt[k].ch[!rev] = 0; // 与分出去的结点断开联系 52 | } 53 | else sgt[n].ch[!rev] = split(sgt[k].ch[!rev], kth - val, rev); // 如果在靠后子树,直接分裂即可,因为靠前子树还是应该属于老树 54 | return n; 55 | } 56 | typedef tuple tp3; // <维护区间的左端点,是否倒序排序,根结点编号> 57 | struct Cmp // 只以存放的数字个数来去重,不写这个仿函数就会因为继续比较tuple的另两个元素而导致未去重 58 | { 59 | bool operator() (const tp3 t1, const tp3 t2) const 60 | { 61 | return get<0>(t1) < get<0>(t2); 62 | } 63 | }; 64 | set rt; 65 | // 以下为STL花活取序列 66 | void data(int l, int r, int k, vector& v) 67 | { 68 | if(!k) return; 69 | if(l==r) v.push_back(l); 70 | int m = (l+r)>>1; 71 | data(l, m, ls(k), v); 72 | data(m+1, r, rs(k), v); 73 | } 74 | vector print(int l, int r) 75 | { 76 | vector ret; 77 | for(auto t : rt) 78 | { 79 | vector v; 80 | data(l, r, get<2>(t), v); 81 | if(get<1>(t)) ret.insert(ret.end(), v.rbegin(), v.rend()); 82 | else ret.insert(ret.end(), v.begin(), v.end()); 83 | } 84 | return ret; 85 | } 86 | auto split(int p) // 使得rt中存在以p为区间左端点的元素 87 | { 88 | auto it = rt.lower_bound(tp3(p, false, 0)); 89 | if(get<0>(*it)==p) return it; // 满足条件(当it==rt.end()时也不会满足这个) 90 | it--; // 否则p一定在前一个元素中 91 | int l,n; bool rev; 92 | tie(l, rev, n) = *it; 93 | return rt.insert(tp3(p, rev, split(n, p-l, rev))).first; // 给剩下p-l个元素,其余的分裂成新树,这样p就会是其所在线段树维护区间的左端点了 94 | } 95 | void solve(int l, int r, bool rev) 96 | { 97 | if(l>r) return; 98 | auto itl = split(l), itr = split(r+1); // 良好的习惯:左闭右开区间,便于下面的for操作 99 | int n = 0; 100 | for(auto it = itl; it!=itr; ++it) 101 | merge(n, get<2>(*it)); // 为使他们具有相同的排序顺序,合并起来再塞回去 102 | rt.erase(itl, itr); // 从rt中删去老信息 103 | rt.insert(tp3(l, rev, n)); // 塞回去 104 | } 105 | signed main(signed argc, char const *argv[]) 106 | { 107 | clock_t c1 = clock(); 108 | #ifdef LOCAL 109 | freopen("in.in", "r", stdin); 110 | freopen("out.out", "w", stdout); 111 | #endif 112 | //====================================== 113 | int n,m; 114 | cin>>n>>m; 115 | // AcWing3419/蓝桥杯2021省1CB_I 双向排序 116 | // for(int i=1;i<=n;i++) 117 | // rt.insert(tp3(i, false, modify(1, n, i))); 118 | // while(m--) 119 | // { 120 | // int opt,x; 121 | // cin>>opt>>x; 122 | // if(opt) solve(x, n, false); 123 | // else solve(1, x, true); 124 | // } 125 | // for(auto i : print(1, n)) cout<>p; 131 | rt.insert(tp3(i, 0, modify(0,n,p))); 132 | } 133 | while(m--) 134 | { 135 | int opt,l,r; 136 | cin>>opt>>l>>r; 137 | solve(l,r,opt); 138 | } 139 | int q; 140 | cin>>q; 141 | cout< 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh1 = '\n', hh2 = ' '; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() { buf2[p3] = hh1; } 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh2; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | using FastIO::print; 59 | using FastIO::read; 60 | //====================================== 61 | #include 62 | const int maxn = 2e3+5; 63 | const int maxm = 3e3+5; 64 | inline int add(int a,int b) //∞+x=∞,所以要手写加法函数判断这种情况 65 | { 66 | if(a==0x3f3f3f3f||b==0x3f3f3f3f) return 0x3f3f3f3f; 67 | else return a+b; 68 | } 69 | struct E 70 | { 71 | int u,v,w; 72 | }Edge[maxm<<1]; 73 | int dis[maxn]; 74 | int main(int argc, char const *argv[]) 75 | { 76 | #ifndef ONLINE_JUDGE 77 | freopen("in.in", "r", stdin); 78 | freopen("out.out", "w", stdout); 79 | #endif 80 | clock_t c1 = clock(); 81 | //====================================== 82 | int t; 83 | read(t); 84 | while(t--) 85 | { 86 | memset(Edge,0,sizeof(Edge)); 87 | memset(dis,0x3f,sizeof(dis)); 88 | dis[1]=0; 89 | int n,m,i,k; 90 | read(n,m); 91 | for(i=k=0;i=0) Edge[++k]=(E){v,u,w}; 97 | } 98 | bool flag = false; //以下除了手写加法函数以外其它的都与2P相同 99 | for(int i=1;i .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 137 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 138 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 139 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 140 | */ -------------------------------------------------------------------------------- /Code/扫描线/扫描线.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() {} 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | #define read FastIO::read 59 | #define print FastIO::print 60 | //====================================== 61 | #include 62 | const int maxn = 2e5 + 5; //因为一个矩形有两边所以数据范围要乘2 63 | int v[maxn]; //存放所有横边的y坐标 64 | struct L //四元组 65 | { 66 | int x; //竖边的x坐标 67 | int y1,y2; //竖边的y坐标,y1较小 68 | int state; //是左边还是右边 69 | bool operator<(L oth) { return x>1; 89 | build(l,m,ls(k)); 90 | build(m,r,rs(k)); 91 | } 92 | void modify(int x,int y,int z,int k=1) 93 | { 94 | int l=sgt[k].l,r=sgt[k].r; 95 | if(x<=l&&y>=r) 96 | { 97 | sgt[k].cover+=z; 98 | pushup(k); //与普通线段树的区别 99 | return; 100 | } 101 | if(xsgt[rs(k)].l) modify(x,y,z,rs(k)); //与普通线段树的区别 103 | pushup(k); 104 | } 105 | int main(int argc, char const *argv[]) 106 | { 107 | #ifndef ONLINE_JUDGE 108 | freopen("in.in", "r", stdin); 109 | freopen("out.out", "w", stdout); 110 | #endif 111 | clock_t c1 = clock(); 112 | //====================================== 113 | int a,b,c,d,n; 114 | read(n); 115 | for(int i=1;i<=n;i++) //读入数据,位置无所谓,待会要排序 116 | { 117 | read(a,b,c,d); 118 | v[i]=b,v[n+i]=d; 119 | line[i]=(L){a,b,d,1},line[n+i]=(L){c,b,d,-1}; 120 | } 121 | std::sort(v+1,v+1+(n<<1)); 122 | std::sort(line+1,line+1+(n<<1)); 123 | build(1,n<<1); 124 | unsigned long long ans = 0; //爆int的毒瘤数据只好用ull处理 125 | for(int i=1;i<=n<<1;i++) 126 | { 127 | ans += sgt[1].len*(line[i].x-line[i-1].x); //注意两语句顺序 128 | modify(line[i].y1,line[i].y2,line[i].state); 129 | } 130 | print(ans); 131 | //====================================== 132 | FastIO::flush(); 133 | std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 134 | return 0; 135 | } 136 | /* 137 | * ┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐ 138 | * │Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ ┌┐ ┌┐ ┌┐ 139 | * └───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘ └┘ └┘ └┘ 140 | * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐ 141 | * │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │Num│ / │ * │ - │ 142 | * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤ 143 | * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │ 144 | * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │ 145 | * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │ 146 | * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤ 147 | * │ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 148 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 149 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 150 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 151 | */ -------------------------------------------------------------------------------- /Code/平衡树系列/fhq Treap/fhq Treap(文艺平衡树).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() {} 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | #define read FastIO::read 59 | #define print FastIO::print 60 | //====================================== 61 | const int maxn = 1e5+5; 62 | struct Node 63 | { 64 | int l,r; 65 | int val,key; 66 | int size; 67 | bool reverse; 68 | }fhq[maxn]; 69 | int cnt,root; 70 | #include 71 | std::mt19937 rnd(233); 72 | inline int newnode(int val) 73 | { 74 | fhq[++cnt].val=val; 75 | fhq[cnt].key=rnd(); 76 | fhq[cnt].size=1; 77 | return cnt; 78 | } 79 | inline void update(int now) 80 | { 81 | fhq[now].size=fhq[fhq[now].l].size+fhq[fhq[now].r].size+1; 82 | } 83 | inline void pushdown(int now) 84 | { 85 | std::swap(fhq[now].l,fhq[now].r); 86 | fhq[fhq[now].l].reverse^=1; 87 | fhq[fhq[now].r].reverse^=1; 88 | fhq[now].reverse=false; 89 | } 90 | void split(int now,int siz,int &x,int &y) 91 | { 92 | if(!now) x=y=0; 93 | else 94 | { 95 | if(fhq[now].reverse) pushdown(now); 96 | if(fhq[fhq[now].l].size .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 180 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 181 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 182 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 183 | */ -------------------------------------------------------------------------------- /Code/左偏树/洛谷P3377 左偏树.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh1 = '\n', hh2 = ' '; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() { buf2[p3] = hh1; } 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh2; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | using FastIO::print; 59 | using FastIO::read; 60 | //====================================== 61 | const int maxn = 1e5+5; 62 | struct Node 63 | { 64 | int l,r,fa; //l,r分别为左右儿子编号;fa为并查集,不属于左偏树,不属于左偏树,不属于左偏树 65 | int val,dis; //val为结点键值,val==-1代表结点被删除;dis为结点的距离 66 | }ltt[maxn]; //内存池写法,与平衡树主席树相同 67 | #define ls(x) ltt[x].l //懒人专用define 68 | #define rs(x) ltt[x].r 69 | inline int merge(int x,int y) //合并两堆,x,y都是堆顶元素的编号 70 | { 71 | if(!x||!y) return x+y; //如果有空的返回另一个,与fhq-Treap相同 72 | //? 或前语句是为了维护小根堆性质,或后语句是题目要求的(值相同则下标小的优先级高) 73 | if(ltt[x].val>ltt[y].val||(ltt[x].val==ltt[y].val&&x>y)) 74 | std::swap(x,y); 75 | rs(x)=merge(rs(x),y); //合并右子树和y 76 | ltt[rs(x)].fa=x; //维护并查集,x的右儿子的父亲肯定是x 77 | if(ltt[ls(x)].dis .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 149 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 150 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 151 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 152 | */ -------------------------------------------------------------------------------- /Code/动态DP/动态DP.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | const int MAXN = 1e5+5; 6 | const int INF = 0x3f3f3f3f; //极大值,-INF就是极小值 7 | //! 这里注意极小值不能使用INT_MIN,因为修改操作有负数,会导致小爆INT 8 | //链式前向星存图 9 | struct E { int to,next; } Edge[MAXN<<1]; 10 | int tot,Head[MAXN]; 11 | inline void AddEdge(int u,int v) 12 | { 13 | Edge[tot]=(E){v, Head[u]}; 14 | Head[u]=tot++; 15 | } 16 | //! 这个矩阵模板写错了不要学 17 | template 18 | struct Matrix 19 | { 20 | int r,c; 21 | int ele[row][col]; //元素 22 | Matrix():r(row),c(col) {} 23 | int& operator()(int a,int b) { return ele[a][b]; } //用括号运算符获取矩阵中元素 24 | }; 25 | template 26 | auto operator*(Matrix m1,Matrix m2) //如果不用C++14就要把前面的auto换成Matrix 27 | { 28 | Matrix ret; //用于存储结果 29 | //? 因为新的矩乘法则,初始化为极小值 30 | memset(ret.ele,0xcf,sizeof(ret.ele)); 31 | for(int i=0;i ident,g[MAXN]; //ident为单位矩阵,在主函数中初始化,g为矩阵池,存放x结点的矩阵是什么 38 | int val[MAXN],f[2][MAXN]; //val存放各结点权值,f用于初始化矩阵池g 39 | //树链剖分第一遍dfs,与普通树链剖分无区别 40 | int fa[MAXN],dep[MAXN],siz[MAXN],son[MAXN]; 41 | void dfs1(int u,int f) 42 | { 43 | fa[u]=f,siz[u]=1,dep[u]=dep[f]+1; 44 | for(int i=Head[u];~i;i=Edge[i].next) 45 | { 46 | int v = Edge[i].to; 47 | if(v==f) continue; 48 | dfs1(v,u); 49 | siz[u]+=siz[v]; 50 | if(siz[v]>siz[son[u]]) 51 | son[u]=v; 52 | } 53 | } 54 | //树链剖分第二遍dfs,在dfs过程中初始化矩阵池 55 | int tim,dfn[MAXN],nfd[MAXN],top[MAXN],end[MAXN]; 56 | void dfs2(int u,int t) 57 | { 58 | top[u]=t,dfn[u]=++tim,nfd[tim]=u; //nfd[x]存放dfn为x的是哪个结点 59 | if(!son[u]) //如果没有重儿子(没有儿子)即为叶子结点 60 | { 61 | f[1][u]=val[u]; //叶子结点的f 62 | g[u]=ident; //叶子结点的矩阵为单位矩阵 63 | end[u]=u; //叶子结点所在重链尾端即为此叶子结点 64 | return; 65 | } 66 | g[u](1,0)=val[u],g[u](1,1)=-INF; //初始化矩阵,左下角放上点权,右下角一直是INF 67 | dfs2(son[u],t); 68 | end[u]=end[son[u]]; //整条重链的end值都等于最下方叶结点,这样一层一层传上来 69 | for(int i=Head[u];~i;i=Edge[i].next) 70 | { 71 | int v = Edge[i].to; 72 | if(v==fa[u]||v==son[u]) continue; 73 | dfs2(v,v); //这都是轻儿子 74 | g[u](0,0)=g[u](0,1)+=std::max(f[0][v],f[1][v]);//每个轻儿子处理好后,将值加到g(i,0)和g(i,1)里 75 | g[u](1,0)+=f[0][v]; 76 | } 77 | //? g处理好后即可处理f,f再用于处理其父亲结点的g 78 | f[0][u]=g[u](0,0)+std::max(f[0][son[u]],f[1][son[u]]); 79 | f[1][u]=g[u](1,0)+f[0][son[u]]; 80 | } 81 | //线段树 82 | struct Node 83 | { 84 | int l,r; 85 | Matrix<2,2> val; 86 | }sgt[MAXN<<2]; 87 | #define ls(x) (x<<1) 88 | #define rs(x) (x<<1|1) 89 | #define pushup(x) sgt[x].val=sgt[ls(x)].val*sgt[rs(x)].val 90 | void build(int l,int r,int k=1) 91 | { 92 | sgt[k].l=l,sgt[k].r=r; 93 | if(l==r) 94 | { 95 | sgt[k].val=g[nfd[l]]; //在矩阵池里获取应该赋值的矩阵 96 | return; 97 | } 98 | int m = (l+r)>>1; 99 | build(l,m,ls(k)); 100 | build(m+1,r,rs(k)); 101 | pushup(k); 102 | } 103 | auto query(int x,int y,int k=1) //区间查询乘积 104 | { 105 | int l=sgt[k].l,r=sgt[k].r; 106 | if(x<=l&&y>=r) return sgt[k].val; 107 | int m = (l+r)>>1; 108 | Matrix<2,2> ret = ident; //应初始化为单位矩阵 109 | if(x<=m) ret = query(x,y,ls(k)); 110 | if(y>m) ret = ret * query(x,y,rs(k)); //注意右乘 111 | return ret; 112 | } 113 | void modify(int x,int p,int k=1) //单点修改x结点的矩阵为矩阵池中p位置上的矩阵 114 | { 115 | int l=sgt[k].l,r=sgt[k].r; 116 | if(l==r) 117 | { 118 | sgt[k].val=g[p]; 119 | return; 120 | } 121 | int m = (l+r)>>1; 122 | if(x<=m) modify(x,p,ls(k)); 123 | else modify(x,p,rs(k)); 124 | pushup(k); 125 | } 126 | auto queryt(int x) //查询x结点的f(x,0),f(x,1)矩阵 127 | { 128 | Matrix<2,1> tmp; 129 | tmp(0,0)=0,tmp(1,0)=val[end[x]]; //初始矩阵,PPT里有说 130 | return query(dfn[x],dfn[end[x]]) * tmp; //注意左乘 131 | } 132 | void modifyt(int x,int z) //单点修改x结点的权值为z 133 | { 134 | Matrix<2,1> od,nw; 135 | g[x](1,0)+=z-val[x]; //相当于先减val[x]再加z,加法交换律 136 | od = queryt(top[x]); //修改之前先查询一个旧的矩阵 137 | val[x]=z; //然后修改,因为queryt函数里初始矩阵是用val[x]算出来的 138 | while(x) //只要x没跳到头,这样写的话主函数里dfs1调用时第二个参数就必须为0 139 | { 140 | modify(dfn[x],x); //先修改 141 | nw = queryt(top[x]); //再查一个新的矩阵出来 142 | x = fa[top[x]]; 143 | //? 在矩阵池里修改,用于下次线段树上修改 144 | g[x](0,0)=g[x](0,1)+=std::max(nw(0,0),nw(1,0))-std::max(od(0,0),od(1,0)); 145 | g[x](1,0)+=nw(0,0)-od(0,0); 146 | od = queryt(top[x]); //下次修改之前先查一个老的出来 147 | } 148 | } 149 | int main(int argc, char const *argv[]) 150 | { 151 | #ifdef LOCAL 152 | freopen("in.in", "r", stdin); 153 | freopen("out.out", "w", stdout); 154 | #endif 155 | clock_t c1 = clock(); 156 | //====================================== 157 | memset(Head,-1,sizeof(Head)); //链式前向星-1写法 158 | ident(1,0)=ident(0,1)=-INF; //单位矩阵赋值 159 | int n,m; 160 | std::cin>>n>>m; 161 | for(int i=1;i<=n;i++) std::cin>>val[i]; 162 | for(int i=1;i>u>>v; 166 | AddEdge(u,v),AddEdge(v,u); 167 | } 168 | dfs1(1,0); //这里注意(1,0) 169 | dfs2(1,1); 170 | build(1,n); 171 | while(m--) 172 | { 173 | int x,z; 174 | std::cin>>x>>z; 175 | modifyt(x,z); 176 | auto ans = queryt(1); //查询根结点矩阵,结果为一个2×1矩阵 177 | std::cout<< std::max(ans(0,0),ans(1,0)) << std::endl; //查出的矩阵中较大的元素即为答案 178 | } 179 | //====================================== 180 | std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 181 | return 0; 182 | } 183 | -------------------------------------------------------------------------------- /Code/平衡树系列/fhq Treap/fhq Treap(普通平衡树).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() {} 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | #define read FastIO::read 59 | #define print FastIO::print 60 | //====================================== 61 | const int maxn = 1e5+5; 62 | struct Node 63 | { 64 | int l,r; 65 | int val,key; 66 | int size; 67 | }fhq[maxn]; 68 | int cnt,root; 69 | #include 70 | std::mt19937 rnd(233); 71 | inline int newnode(int val) 72 | { 73 | fhq[++cnt].val=val; 74 | fhq[cnt].key=rnd(); 75 | fhq[cnt].size=1; 76 | return cnt; 77 | } 78 | inline void update(int now) 79 | { 80 | fhq[now].size=fhq[fhq[now].l].size+fhq[fhq[now].r].size+1; 81 | } 82 | void split(int now,int val,int &x,int &y) 83 | { 84 | if(!now) x=y=0; 85 | else 86 | { 87 | if(fhq[now].val<=val) 88 | { 89 | x=now; 90 | split(fhq[now].r,val,fhq[now].r,y); 91 | } 92 | else 93 | { 94 | y=now; 95 | split(fhq[now].l,val,x,fhq[now].l); 96 | } 97 | update(now); 98 | } 99 | } 100 | int merge(int x,int y) 101 | { 102 | if(!x||!y) return x+y; 103 | if(fhq[x].key>fhq[y].key) // > >= < <= 104 | { 105 | fhq[x].r=merge(fhq[x].r,y); 106 | update(x); 107 | return x; 108 | } 109 | else 110 | { 111 | fhq[y].l=merge(x,fhq[y].l); 112 | update(y); 113 | return y; 114 | } 115 | } 116 | int x,y,z; 117 | inline void ins(int val) 118 | { 119 | split(root,val,x,y); 120 | root=merge(merge(x,newnode(val)),y); 121 | } 122 | inline void del(int val) 123 | { 124 | split(root,val,x,z); 125 | split(x,val-1,x,y); 126 | y=merge(fhq[y].l,fhq[y].r); 127 | root=merge(merge(x,y),z); 128 | } 129 | inline void getrank(int val) 130 | { 131 | split(root,val-1,x,y); 132 | print(fhq[x].size+1); 133 | root=merge(x,y); 134 | } 135 | inline void getnum(int rank) 136 | { 137 | int now=root; 138 | while(now) 139 | { 140 | if(fhq[fhq[now].l].size+1==rank) 141 | break; 142 | else if(fhq[fhq[now].l].size>=rank) 143 | now=fhq[now].l; 144 | else 145 | { 146 | rank-=fhq[fhq[now].l].size+1; 147 | now=fhq[now].r; 148 | } 149 | } 150 | print(fhq[now].val); 151 | } 152 | inline void pre(int val) 153 | { 154 | split(root,val-1,x,y); 155 | int now = x; 156 | while(fhq[now].r) 157 | now = fhq[now].r; 158 | print(fhq[now].val); 159 | root=merge(x,y); 160 | } 161 | inline void nxt(int val) 162 | { 163 | split(root,val,x,y); 164 | int now = y; 165 | while(fhq[now].l) 166 | now = fhq[now].l; 167 | print(fhq[now].val); 168 | root=merge(x,y); 169 | } 170 | int main(int argc, char const *argv[]) 171 | { 172 | #ifndef ONLINE_JUDGE 173 | freopen("in.in", "r", stdin); 174 | freopen("out.out", "w", stdout); 175 | #endif 176 | clock_t c1 = clock(); 177 | //====================================== 178 | int t; 179 | read(t); 180 | while(t--) 181 | { 182 | int opt,x; 183 | read(opt,x); 184 | switch(opt) 185 | { 186 | case 1: 187 | ins(x); 188 | break; 189 | case 2: 190 | del(x); 191 | break; 192 | case 3: 193 | getrank(x); 194 | break; 195 | case 4: 196 | getnum(x); 197 | break; 198 | case 5: 199 | pre(x); 200 | break; 201 | case 6: 202 | nxt(x); 203 | break; 204 | } 205 | } 206 | //====================================== 207 | FastIO::flush(); 208 | std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 209 | return 0; 210 | } 211 | /* 212 | * ┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐ 213 | * │Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ ┌┐ ┌┐ ┌┐ 214 | * └───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘ └┘ └┘ └┘ 215 | * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐ 216 | * │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │Num│ / │ * │ - │ 217 | * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤ 218 | * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │ 219 | * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │ 220 | * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │ 221 | * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤ 222 | * │ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 223 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 224 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 225 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 226 | */ 227 | -------------------------------------------------------------------------------- /Code/点分治/点分治.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh1 = '\n', hh2 = ' '; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() { buf2[p3] = hh1; } 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh2; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | using FastIO::print; 59 | using FastIO::read; 60 | //====================================== 61 | const int maxn = 1e4+5; 62 | const int maxk = 1e7+5; 63 | struct E 64 | { 65 | int to,w,next; 66 | }Edge[maxn<<1]; 67 | int tot,Head[maxn]; 68 | inline void AddEdge(int u,int v,int w) 69 | { 70 | Edge[tot]=(E){v,w,Head[u]}; 71 | Head[u]=tot++; 72 | } 73 | //? rt记录重心,sum记录当前树大小,cnt是计数器 74 | int n,m,rt,sum,cnt; 75 | //? tmp记录算出的距离,siz记录子树大小,dis[i]为rt与i之间的距离 76 | //? maxp用于找重心,q用于记录所有询问 77 | int tmp[maxn],siz[maxn],dis[maxn],maxp[maxn],q[105]; 78 | //? judge[i]记录在之前子树中距离i是否存在,ans记录第k个询问是否存在,vis记录被删除的结点 79 | bool judge[maxk],ans[105],vis[maxn]; 80 | //TODO 找重心 81 | void getrt(int u,int f) 82 | { 83 | siz[u]=1,maxp[u]=0; //maxp初始化为最小值 84 | //遍历所有儿子,用maxp保存最大大小的儿子的大小 85 | for(int i=Head[u];~i;i=Edge[i].next) 86 | { 87 | int v = Edge[i].to; 88 | if(v==f||vis[v]) continue; //被删掉的也不要算 89 | getrt(v,u); 90 | siz[u]+=siz[v]; 91 | if(siz[v]>maxp[u]) maxp[u]=siz[v]; //更新maxp 92 | } 93 | maxp[u]=std::max(maxp[u],sum-siz[u]); //考虑u的祖先结点 94 | if(maxp[u] 109 | //TODO 处理经过根结点的路径 110 | //! 注意judge数组要存放之前子树里存在的路径长度,排除折返路径的可能 111 | void solve(int u) 112 | { 113 | static std::queue que; 114 | for(int i=Head[u];~i;i=Edge[i].next) 115 | { 116 | int v = Edge[i].to; 117 | if(vis[v]) continue; 118 | cnt=0; //注意置零计数器 119 | dis[v]=Edge[i].w; 120 | getdis(v,u); //把距离都处理出来 121 | for(int j=0;j=tmp[j]) //如果询问大于单条路径长度,那就有可能存在 124 | ans[k]|=judge[q[k]-tmp[j]]; //如果能用两条路径拼出来,那就存在 125 | for(int j=0;j 153 | int main(int argc, char const *argv[]) 154 | { 155 | #ifndef ONLINE_JUDGE 156 | freopen("in.in", "r", stdin); 157 | freopen("out.out", "w", stdout); 158 | #endif 159 | clock_t c1 = clock(); 160 | //====================================== 161 | memset(Head,-1,sizeof(Head)); 162 | read(n,m); 163 | for(int i=1;i .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 198 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 199 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 200 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 201 | */ -------------------------------------------------------------------------------- /Code/点分治/经典例题 洛谷P4178&&POJ1741 Tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh1 = '\n', hh2 = ' '; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() { buf2[p3] = hh1; } 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh2; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | using FastIO::print; 59 | using FastIO::read; 60 | //====================================== 61 | const int maxn = 4e4+5; 62 | struct E 63 | { 64 | int to,w,next; 65 | }Edge[maxn<<1]; 66 | int tot,Head[maxn]; 67 | inline void AddEdge(int u,int v,int w) 68 | { 69 | Edge[tot]=(E){v,w,Head[u]}; 70 | Head[u]=tot++; 71 | } 72 | int n,k; 73 | int siz[maxn],maxp[maxn],rt,sum; 74 | bool vis[maxn]; 75 | void getrt(int u,int f) 76 | { 77 | siz[u]=1,maxp[u]=0; 78 | for(int i=Head[u];~i;i=Edge[i].next) 79 | { 80 | int v = Edge[i].to; 81 | if(v==f||vis[v]) continue; 82 | getrt(v,u); 83 | siz[u]+=siz[v]; 84 | if(siz[v]>maxp[u]) maxp[u]=siz[v]; 85 | } 86 | maxp[u]=std::max(maxp[u],sum-siz[u]); 87 | if(maxp[u]>1; 102 | build(l,m,ls(k)); 103 | build(m+1,r,rs(k)); 104 | } 105 | void modify(int x,int z,int k=1) 106 | { 107 | int l=sgt[k].l,r=sgt[k].r; 108 | if(l==r) 109 | { 110 | sgt[k].val+=z; 111 | return; 112 | } 113 | int m = (l+r)>>1; 114 | if(x<=m) modify(x,z,ls(k)); 115 | else modify(x,z,rs(k)); 116 | pushup(k); 117 | } 118 | int query(int x,int y,int k=1) 119 | { 120 | if(x>y) return 0; 121 | int l=sgt[k].l,r=sgt[k].r; 122 | if(x<=l&&y>=r) return sgt[k].val; 123 | int m = (l+r)>>1; 124 | int sum = 0; 125 | if(x<=m) sum+=query(x,y,ls(k)); 126 | if(y>m) sum+=query(x,y,rs(k)); 127 | return sum; 128 | } 129 | int cnt,tmp[maxn],dis[maxn]; 130 | void getdis(int u,int f) 131 | { 132 | tmp[cnt++]=dis[u]; 133 | for(int i=Head[u];~i;i=Edge[i].next) 134 | { 135 | int v = Edge[i].to; 136 | if(v==f||vis[v]) continue; 137 | dis[v]=dis[u]+Edge[i].w; 138 | getdis(v,u); 139 | } 140 | } 141 | #include 142 | int ans; 143 | void solve(int u) 144 | { 145 | static std::queue q; 146 | for(int i=Head[u];~i;i=Edge[i].next) 147 | { 148 | int v = Edge[i].to; 149 | if(vis[v]) continue; 150 | cnt=0; 151 | dis[v]=Edge[i].w; 152 | getdis(v,u); 153 | for(int j=0;j=tmp[j]) 155 | ans+=query(1,k-tmp[j])+1; 156 | for(int j=0;j 183 | int main(int argc, char const *argv[]) 184 | { 185 | #ifndef ONLINE_JUDGE 186 | freopen("in.in", "r", stdin); 187 | freopen("out.out", "w", stdout); 188 | #endif 189 | clock_t c1 = clock(); 190 | //====================================== 191 | memset(Head,-1,sizeof(Head)); 192 | read(n); 193 | for(int i=1;i .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 224 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 225 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 226 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 227 | */ -------------------------------------------------------------------------------- /Code/Link Cut Tree/Link Cut Tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() {} 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | #define read FastIO::read 59 | #define print FastIO::print 60 | //====================================== 61 | const int maxn = 1e5+5; 62 | struct Node 63 | { 64 | int fa,ch[2],val,res; //res是异或结果 65 | bool tag; //翻转懒标记 66 | }spl[maxn]; 67 | //因为被毒瘤数据卡得TLE一个点,所以全部换成了#define。都是字面意思 68 | #define ls(x) (spl[x].ch[0]) 69 | #define rs(x) (spl[x].ch[1]) 70 | #define fa(x) (spl[x].fa) 71 | #define ident(x,f) (rs(f)==x) //和下面的connect都是Splay的辅助函数 72 | #define connect(x,f,s) spl[fa(x)=f].ch[s]=x 73 | #define update(x) spl[x].res=spl[ls(x)].res^spl[rs(x)].res^spl[x].val 74 | #define ntroot(x) (ls(fa(x))==x||rs(fa(x))==x) //判断结点是否为Splay的根 75 | #define reverse(x) std::swap(ls(x),rs(x)),spl[x].tag^=1 76 | inline void pushdw(int x) //懒标记下传 77 | { 78 | if(spl[x].tag) 79 | { 80 | if(ls(x)) reverse(ls(x)); 81 | if(rs(x)) reverse(rs(x)); 82 | } 83 | spl[x].tag=0; 84 | } 85 | void pushall(int x) //头递归,从上到下下传所有懒标记 86 | { 87 | if(ntroot(x)) pushall(fa(x)); 88 | pushdw(x); 89 | } 90 | inline void rotate(int x) //Splay基操 91 | { 92 | int f=fa(x),ff=fa(f),k=ident(x,f); 93 | connect(spl[x].ch[k^1],f,k); 94 | fa(x)=ff; 95 | if(ntroot(f)) spl[ff].ch[ident(f,ff)]=x;//※重要,不能忘记判断,关系到虚实边 96 | connect(f,x,k^1); 97 | update(f),update(x); 98 | } 99 | inline void splaying(int x) //Splay基操,都是伸展到根结点 100 | { 101 | pushall(x); //要先把上面的懒标记全都下传 102 | while(ntroot(x)) 103 | { 104 | int f=fa(x),ff=fa(f); 105 | if(ntroot(f)) ident(f,ff)^ident(x,f)?rotate(x):rotate(f); 106 | rotate(x); 107 | } 108 | } 109 | inline void access(int x) //从x到原树根结点拉一条实链 110 | { 111 | for(int y=0;x;x=fa(y=x)) //y为上一个Splay的根 112 | { 113 | splaying(x); //伸展到当前Splay的根 114 | rs(x)=y; //右儿子连上上一个Splay的根 115 | update(x); //别忘更新>﹏< 116 | } 117 | } 118 | inline void mkroot(int x) //给原树换根 119 | { 120 | access(x); //先拉实链,拉好后x一定在Splay的最右(深度最大) 121 | splaying(x); //再伸展,伸展后x必定没有右儿子 122 | reverse(x); //翻转拉出来这条实链,使深度顺序翻转 123 | } 124 | inline int findroot(int x) //寻找结点在原树的根 125 | { 126 | access(x); //先拉实链 127 | splaying(x); //再伸展 128 | while(ls(x)) //因为根结点必定深度最小,所以不停往左找就OK了 129 | { 130 | pushdw(x); //别忘了下传,第一个儿子是没问题的但是第二个往后…… 131 | x=ls(x); 132 | } 133 | splaying(x); //用来保证时间复杂度,防止卡链 134 | return x; 135 | } 136 | inline void link(int x,int y) //连边,不保证数据合法 137 | { 138 | mkroot(x); //换根 139 | if(findroot(y)==x) return; //如果y所在的树的根结点是x,那说明两者在一棵树上 140 | fa(x)=y; 141 | } 142 | inline void cut(int x,int y) //断边,不保证数据合法 143 | { 144 | mkroot(x); //换根 145 | //? 如果y跟x不在一棵树上 or x和y之间不是紧紧挨着的,return 146 | //! 注意这里findroot后由于保证复杂度的一句伸展,导致刚才被换成根的x成为了Splay的根结点 147 | //* 又因为x在原树中是根结点,深度最小,所以在Splay中一定是x为根结点y为其右儿子 148 | if(findroot(y)!=x||fa(y)!=x||ls(y)) return; 149 | fa(y)=rs(x)=0; //双向断边 150 | update(x); //别忘更新>﹏< 151 | } 152 | inline void split(int x,int y) //把x--y的路径拆出来 153 | { 154 | mkroot(x); //换根 155 | access(y); //拉实链 156 | splaying(y); //伸展 157 | //? 此时y必定没有右儿子且左儿子是一条到x的实链,所以访问y就可以作任何关于这条链的操作了 158 | } 159 | int main(int argc, char const *argv[]) 160 | { 161 | #ifndef ONLINE_JUDGE 162 | freopen("in.in", "r", stdin); 163 | freopen("out.out", "w", stdout); 164 | #endif 165 | clock_t c1 = clock(); 166 | //====================================== 167 | int n,m; 168 | read(n,m); 169 | //? 刚开始的时候所有点之间都没连着 170 | for(int i=1;i<=n;i++) read(spl[i].val); 171 | while(m--) 172 | { 173 | int opt,x,y; 174 | read(opt,x,y); 175 | switch(opt) 176 | { 177 | case 0: 178 | split(x,y); 179 | print(spl[y].res); //访问y就相当于访问这条链了 180 | break; 181 | case 1: 182 | link(x,y); 183 | break; 184 | case 2: 185 | cut(x,y); 186 | break; 187 | case 3: 188 | splaying(x); //注意要先伸展到根,否则会很麻烦 189 | spl[x].val=y; 190 | update(x); //不更新也没啥问题,加不加都行 191 | break; 192 | } 193 | } 194 | //====================================== 195 | FastIO::flush(); 196 | std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 197 | return 0; 198 | } 199 | /* 200 | * ┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐ 201 | * │Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ ┌┐ ┌┐ ┌┐ 202 | * └───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘ └┘ └┘ └┘ 203 | * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐ 204 | * │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │Num│ / │ * │ - │ 205 | * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤ 206 | * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │ 207 | * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │ 208 | * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │ 209 | * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤ 210 | * │ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 211 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 212 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 213 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 214 | */ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /Code/平衡树系列/AVL树/AVL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() {} 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | #define read FastIO::read 59 | #define print FastIO::print 60 | //====================================== 61 | const int maxn = 1e5+5; 62 | struct Node 63 | { 64 | int l,r; 65 | int val; 66 | int height,size; 67 | }avl[maxn]; //内存池,老生常谈 68 | int cnt,root; 69 | inline void newnode(int &now,int val) //新建结点,老生常谈 70 | { 71 | avl[now=++cnt].val=val; 72 | avl[cnt].size=1; 73 | } 74 | inline void update(int now) //更新节点信息 75 | { 76 | avl[now].size=avl[avl[now].l].size+avl[avl[now].r].size+1; 77 | avl[now].height=std::max(avl[avl[now].l].height,avl[avl[now].r].height)+1; 78 | } 79 | inline int factor(int now) //获取BF 80 | { 81 | return avl[avl[now].l].height-avl[avl[now].r].height; 82 | } 83 | inline void lrotate(int &now) //左旋 84 | { 85 | int r = avl[now].r; 86 | avl[now].r = avl[r].l; 87 | avl[r].l = now; 88 | now = r; 89 | update(avl[now].l),update(now); 90 | } 91 | inline void rrotate(int &now) //右旋 92 | { 93 | int l = avl[now].l; 94 | avl[now].l = avl[l].r; 95 | avl[l].r = now; 96 | now = l; 97 | update(avl[now].r),update(now); 98 | } 99 | inline void check(int &now)//检查是否需要旋转,并且更新节点信息 100 | { 101 | int nf = factor(now); 102 | if(nf>1) 103 | { 104 | int lf = factor(avl[now].l); 105 | if(lf>0) rrotate(now); //LL 106 | else lrotate(avl[now].l),rrotate(now); //LR 107 | } 108 | else if(nf<-1) 109 | { 110 | int rf = factor(avl[now].r); 111 | if(rf<0) lrotate(now); //RR 112 | else rrotate(avl[now].r),lrotate(now); //RL 113 | } 114 | else if(now) update(now);//如果平衡并且非空,那就直接更新 115 | } 116 | void ins(int &now,int val) 117 | { 118 | if(!now) newnode(now,val); //到了一个不存在的点,新建它 119 | else if(val=rank) 186 | now=avl[now].l; 187 | else 188 | { 189 | rank-=avl[avl[now].l].size+1; 190 | now=avl[now].r; 191 | } 192 | } 193 | return avl[now].val; 194 | } 195 | int main(int argc, char const *argv[]) 196 | { 197 | #ifndef ONLINE_JUDGE 198 | freopen("in.in", "r", stdin); 199 | freopen("out.out", "w", stdout); 200 | #endif 201 | clock_t c1 = clock(); 202 | //====================================== 203 | int t; 204 | read(t); 205 | while(t--) 206 | { 207 | int opt,x; 208 | read(opt,x); 209 | switch(opt) 210 | { 211 | case 1: 212 | ins(root,x); 213 | break; 214 | case 2: 215 | del(root,x); 216 | break; 217 | case 3: 218 | print(getrank(x)); 219 | break; 220 | case 4: 221 | print(getnum(x)); 222 | break; 223 | case 5: 224 | print(getnum(getrank(x)-1)); 225 | break; 226 | case 6: 227 | print(getnum(getrank(x+1))); 228 | break; 229 | } 230 | } 231 | //====================================== 232 | FastIO::flush(); 233 | std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 234 | return 0; 235 | } 236 | /* 237 | * ┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐ 238 | * │Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ ┌┐ ┌┐ ┌┐ 239 | * └───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘ └┘ └┘ └┘ 240 | * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐ 241 | * │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │Num│ / │ * │ - │ 242 | * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤ 243 | * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │ 244 | * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │ 245 | * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │ 246 | * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤ 247 | * │ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 248 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 249 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 250 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 251 | */ -------------------------------------------------------------------------------- /Code/平衡树系列/Splay/Splay(普通平衡树).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() {} 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | #define read FastIO::read 59 | #define print FastIO::print 60 | //====================================== 61 | const int maxn = 1e5+5; 62 | struct Node 63 | { 64 | int l,r; 65 | int val,size; 66 | int cnt; //当前结点重复次数,默认为1 67 | }spl[maxn]; //内存池 68 | int cnt,root; //内存池计数器与根节点编号 69 | inline void newnode(int &now,int &val) 70 | { 71 | spl[now=++cnt].val=val; 72 | spl[cnt].size++; 73 | spl[cnt].cnt++; 74 | } 75 | inline void update(int now) //更新size 76 | { 77 | spl[now].size=spl[spl[now].l].size+spl[spl[now].r].size+spl[now].cnt; 78 | } 79 | inline void zig(int &now) 80 | { 81 | int l = spl[now].l; 82 | spl[now].l = spl[l].r; 83 | spl[l].r = now; 84 | now = l; 85 | update(spl[now].r),update(now); 86 | } 87 | inline void zag(int &now) 88 | { 89 | int r = spl[now].r; 90 | spl[now].r = spl[r].l; 91 | spl[r].l = now; 92 | now = r; 93 | update(spl[now].l),update(now); 94 | } 95 | void splaying(int x,int &y) //我要把x伸展到y那个位置! 96 | { 97 | if(x==y) return; //如果到了终点,return 98 | int &l = spl[y].l, &r = spl[y].r; //temp 99 | if(x==l) zig(y); //如果左儿子是终点,那就单旋 100 | else if(x==r) zag(y); //右儿子是终点也是单旋 101 | else //否则就一定是双旋 102 | { 103 | if(spl[x].valspl[r].val) 112 | splaying(x,spl[r].r),zag(y),zag(y); //zagzag情况 113 | else splaying(x,spl[r].l),zig(r),zag(y); //zigzag情况 114 | } 115 | } 116 | } 117 | inline void delnode(int now) 118 | { 119 | splaying(now,root); //将要删除的结点伸展至根结点 120 | if(spl[now].cnt>1) spl[now].size--,spl[now].cnt--; //如果有重复,令重复次数-- 121 | else if(spl[root].r) //否则如果当前结点有后继 122 | { 123 | int p = spl[root].r; 124 | while(spl[p].l) p=spl[p].l; //找到后继 125 | splaying(p,spl[root].r); //将其伸展至根结点右儿子 126 | spl[spl[root].r].l=spl[root].l; //右儿子左儿子变为根结点 127 | root=spl[root].r; //根结点变为根结点右儿子 128 | update(root); //更新一下size信息 129 | } 130 | else root = spl[root].l; //伸展之后没有后继,说明它是最大的了,那就直接删除 131 | } 132 | void ins(int &now,int &val) 133 | { 134 | if(!now) newnode(now,val),splaying(now,root); 135 | else if(valspl[now].val) ins(spl[now].r,val); 137 | else spl[now].size++,spl[now].cnt++,splaying(now,root); //特判相同的情况 138 | } 139 | void del(int now,int &val) 140 | { 141 | if(spl[now].val==val) delnode(now); 142 | else if(val=rank) 179 | now=spl[now].l; 180 | else 181 | { 182 | rank-=lsize+spl[now].cnt; 183 | now=spl[now].r; 184 | } 185 | } 186 | return spl[now].val; 187 | } 188 | int main(int argc, char const *argv[]) 189 | { 190 | #ifndef ONLINE_JUDGE 191 | freopen("in.in", "r", stdin); 192 | freopen("out.out", "w", stdout); 193 | #endif 194 | clock_t c1 = clock(); 195 | //====================================== 196 | int t; 197 | read(t); 198 | while(t--) 199 | { 200 | int opt,x; 201 | read(opt,x); 202 | switch(opt) 203 | { 204 | case 1: 205 | ins(root,x); 206 | break; 207 | case 2: 208 | del(root,x); 209 | break; 210 | case 3: 211 | print(getrank(x)); 212 | break; 213 | case 4: 214 | print(getnum(x)); 215 | break; 216 | case 5: 217 | print(getnum(getrank(x)-1)); 218 | break; 219 | case 6: 220 | print(getnum(getrank(x+1))); 221 | break; 222 | } 223 | } 224 | //====================================== 225 | FastIO::flush(); 226 | std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 227 | return 0; 228 | } 229 | /* 230 | * ┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐ 231 | * │Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ ┌┐ ┌┐ ┌┐ 232 | * └───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘ └┘ └┘ └┘ 233 | * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐ 234 | * │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │Num│ / │ * │ - │ 235 | * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤ 236 | * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │ 237 | * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │ 238 | * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │ 239 | * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤ 240 | * │ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 241 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 242 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 243 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 244 | */ -------------------------------------------------------------------------------- /Code/树链剖分/树链剖分.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace FastIO 6 | { 7 | char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 | int p, p3 = -1; 9 | void read() {} 10 | void print() {} 11 | inline int getc() 12 | { 13 | return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 | } 15 | inline void flush() 16 | { 17 | fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 | } 19 | template 20 | inline void read(T &x, T2 &... oth) 21 | { 22 | int f = 0; 23 | x = 0; 24 | char ch = getc(); 25 | while (!isdigit(ch)) 26 | { 27 | if (ch == '-') 28 | f = 1; 29 | ch = getc(); 30 | } 31 | while (isdigit(ch)) 32 | { 33 | x = x * 10 + ch - 48; 34 | ch = getc(); 35 | } 36 | x = f ? -x : x; 37 | read(oth...); 38 | } 39 | template 40 | inline void print(T x, T2... oth) 41 | { 42 | if (p3 > 1 << 20) 43 | flush(); 44 | if (x < 0) 45 | buf2[++p3] = 45, x = -x; 46 | do 47 | { 48 | a[++p] = x % 10 + 48; 49 | } while (x /= 10); 50 | do 51 | { 52 | buf2[++p3] = a[p]; 53 | } while (--p); 54 | buf2[++p3] = hh; 55 | print(oth...); 56 | } 57 | } // namespace FastIO 58 | #define read FastIO::read 59 | #define print FastIO::print 60 | //====================================== 61 | const int maxn = 1e5 + 5; 62 | const int maxm = maxn * 2; 63 | struct E 64 | { 65 | int to, next; 66 | } Edge[maxm]; 67 | int tot, Head[maxn]; 68 | inline void AddEdge(int u, int v) 69 | { 70 | Edge[tot] = (E){v, Head[u]}; 71 | Head[u] = tot++; 72 | Edge[tot] = (E){u, Head[v]}; 73 | Head[v] = tot++; 74 | } 75 | int mod; 76 | int v[maxn]; 77 | int fa[maxn], dep[maxn], siz[maxn], son[maxn]; 78 | void dfs1(int u, int f) 79 | { 80 | fa[u] = f; 81 | dep[u] = dep[f] + 1; 82 | siz[u] = 1; 83 | int maxsize = -1; 84 | for (int i = Head[u]; ~i; i = Edge[i].next) 85 | { 86 | int v = Edge[i].to; 87 | if (v == f) 88 | continue; 89 | dfs1(v, u); 90 | siz[u] += siz[v]; 91 | if (siz[v] > maxsize) 92 | { 93 | maxsize = siz[v]; 94 | son[u] = v; 95 | } 96 | } 97 | } 98 | int tim, dfn[maxn], top[maxn], w[maxn]; 99 | void dfs2(int u, int t) 100 | { 101 | dfn[u] = ++tim; 102 | top[u] = t; 103 | w[tim] = v[u]; 104 | if (!son[u]) 105 | return; 106 | dfs2(son[u], t); 107 | for (int i = Head[u]; ~i; i = Edge[i].next) 108 | { 109 | int v = Edge[i].to; 110 | if (v == fa[u] || v == son[u]) 111 | continue; 112 | dfs2(v, v); 113 | } 114 | } 115 | struct Node 116 | { 117 | int l, r, f, val; 118 | } sgt[maxn * 4]; 119 | inline int ls(int k) { return k << 1; } 120 | inline int rs(int k) { return k << 1 | 1; } 121 | inline void pushup(int k) { sgt[k].val = (sgt[ls(k)].val + sgt[rs(k)].val) % mod; } 122 | inline void pushdown(int k) 123 | { 124 | sgt[ls(k)].f += sgt[k].f; 125 | sgt[rs(k)].f += sgt[k].f; 126 | sgt[ls(k)].val += (sgt[ls(k)].r - sgt[ls(k)].l + 1) * sgt[k].f % mod; 127 | sgt[rs(k)].val += (sgt[rs(k)].r - sgt[rs(k)].l + 1) * sgt[k].f % mod; 128 | sgt[k].f = 0; 129 | } 130 | void build(int l, int r, int k = 1) 131 | { 132 | sgt[k].l = l, sgt[k].r = r; 133 | if (l == r) 134 | { 135 | sgt[k].val = w[l] % mod; 136 | return; 137 | } 138 | int m = (l + r) >> 1; 139 | build(l, m, ls(k)); 140 | build(m + 1, r, rs(k)); 141 | pushup(k); 142 | } 143 | void modify(int x, int y, int z, int k = 1) 144 | { 145 | int l = sgt[k].l, r = sgt[k].r; 146 | if (x <= l && y >= r) 147 | { 148 | sgt[k].f += z; 149 | sgt[k].val += (r - l + 1) * z; 150 | sgt[k].val %= mod; 151 | return; 152 | } 153 | if (sgt[k].f) 154 | pushdown(k); 155 | int m = (l + r) >> 1; 156 | if (x <= m) 157 | modify(x, y, z, ls(k)); 158 | if (y > m) 159 | modify(x, y, z, rs(k)); 160 | pushup(k); 161 | } 162 | int query(int x, int y, int k = 1) 163 | { 164 | int l = sgt[k].l, r = sgt[k].r; 165 | if (x <= l && y >= r) 166 | return sgt[k].val; 167 | if (sgt[k].f) 168 | pushdown(k); 169 | int sum = 0, m = (l + r) >> 1; 170 | if (x <= m) 171 | sum += query(x, y, ls(k)); 172 | if (y > m) 173 | sum += query(x, y, rs(k)); 174 | return sum % mod; 175 | } 176 | void mchain(int x, int y, int z) 177 | { 178 | z %= mod; 179 | while (top[x] != top[y]) 180 | { 181 | if (dep[top[x]] < dep[top[y]]) 182 | std::swap(x, y); 183 | modify(dfn[top[x]], dfn[x], z); 184 | x = fa[top[x]]; 185 | } 186 | if (dep[x] > dep[y]) 187 | std::swap(x, y); 188 | modify(dfn[x], dfn[y], z); 189 | } 190 | int qchain(int x, int y) 191 | { 192 | int ret = 0; 193 | while (top[x] != top[y]) 194 | { 195 | if (dep[top[x]] < dep[top[y]]) 196 | std::swap(x, y); 197 | ret += query(dfn[top[x]], dfn[x]); 198 | x = fa[top[x]]; 199 | } 200 | if (dep[x] > dep[y]) 201 | std::swap(x, y); 202 | ret += query(dfn[x], dfn[y]); 203 | return ret % mod; 204 | } 205 | inline void mson(int x, int z) 206 | { 207 | modify(dfn[x], dfn[x] + siz[x] - 1, z); 208 | } 209 | inline int qson(int x) 210 | { 211 | return query(dfn[x], dfn[x] + siz[x] - 1); 212 | } 213 | #include 214 | int main(int argc, char const *argv[]) 215 | { 216 | #ifndef ONLINE_JUDGE 217 | freopen("in.in", "r", stdin); 218 | freopen("out.out", "w", stdout); 219 | #endif 220 | clock_t c1 = clock(); 221 | //====================================== 222 | memset(Head, -1, sizeof(Head)); 223 | int n, m, r; 224 | read(n, m, r, mod); 225 | for (int i = 1; i <= n; i++) 226 | read(v[i]); 227 | for (int i = 1; i < n; i++) 228 | { 229 | int u, v; 230 | read(u, v); 231 | AddEdge(u, v); 232 | } 233 | dfs1(r, r); 234 | dfs2(r, r); 235 | build(1, n); 236 | while (m--) 237 | { 238 | int opt, x, y, z; 239 | read(opt); 240 | switch (opt) 241 | { 242 | case 1: 243 | read(x, y, z); 244 | mchain(x, y, z); 245 | break; 246 | case 2: 247 | read(x, y); 248 | print(qchain(x, y)); 249 | break; 250 | case 3: 251 | read(x, z); 252 | mson(x, z); 253 | break; 254 | case 4: 255 | read(x); 256 | print(qson(x)); 257 | break; 258 | } 259 | } 260 | //====================================== 261 | FastIO::flush(); 262 | std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 263 | return 0; 264 | } 265 | /* 266 | * ┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐ 267 | * │Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ ┌┐ ┌┐ ┌┐ 268 | * └───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘ └┘ └┘ └┘ 269 | * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐ 270 | * │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │Num│ / │ * │ - │ 271 | * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤ 272 | * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │ 273 | * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │ 274 | * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │ 275 | * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤ 276 | * │ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │ 277 | * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││ 278 | * │ Ctrl│ Win│ Alt│ Space │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│ 279 | * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘ 280 | */ --------------------------------------------------------------------------------