自备ACM模板-数据结构篇
2020-08-02 16:11
711 查看
ST表
// 求区间最值 洛谷 P3865 #include<bits/stdc++.h> using namespace std; int n, k, num[100005]; int ma[100005][25]; // n*logn void pre(){ for(int i = 1; i <= n; i++) ma[i][0] = num[i]; int s = 2, s2; for(int j = 1; s <= n; j++, s <<= 1){ s2 = s; for(int i = 1; s2 <= n; i++, s2++) ma[i][j] = max(ma[i][j - 1], ma[i + (s>>1)][j - 1]); } } int qerry(int l, int r){ int k = trunc(log2(r-l+1)); // floor return max(ma[l][k], ma[r - (1 << k) + 1][k]); } // 精髓就是这个区间查询,按区间长度找到对应层级 int main(){ int q; cin >> n >> q; for(int i = 1; i <= n; i++) cin >> num[i]; pre(); int l, r; for(int i = 1; i <= q; i++){ cin >> l >> r; cout << qerry(l,r)) << endl; } return 0; } // ST表还可以通过时间戳找LCA
主席树
// 找区间内第k小(就是升序第k个的意思) 洛谷 P3834 #include<bits/stdc++.h> using namespace std; typedef long long LL; #define maxn 200005 struct node{ int l, r, sum; }t[maxn*21]; int cnt; LL a[maxn], b[maxn]; int root[maxn]; void update(int l, int r, int &x, int y, int pos){ x = ++cnt; t[x] = t[y]; t[x].sum++; if(l == r) return ; int m = (l + r) >> 1; if(pos <= m) update(l, m, t[x].l, t[y].l, pos); else update(m + 1, r, t[x].r, t[y].r, pos); } LL query(int l, int r, int x, int y, int k){ if(l == r) return b[l]; int m = (l + r) >> 1; int s = t[t[y].l].sum - t[t[x].l].sum; if(k <= s) return query(l, m, t[x].l, t[y].l, k); else return query(m + 1, r, t[x].r, t[y].r, k - s); } int main(){ int tol, n, m, i, l, r, k; cin >> n >> m; for(i=1;i<=n;i++){ cin >> a[i]; b[i] = a[i]; } sort(b + 1, b + n + 1); for(i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b; for(i = 0; i < n; i++) update(1, n, root[i + 1], root[i], a[i + 1]); for(i = 1; i <= m; i++) cin >> l >> r >> k; cout << query(1,n,root[l-1],root[r],k)) << endl; return 0; }
树链剖分
// 更新任意两点到LCA的权值,求任意两点到LCA的权值和 // 更新以任意点为根节点的子树的权值,求以任意点为根节点的子树的权值和 // 洛谷 P3384 #include<bits/stdc++.h> using namespace std; #define maxn 200010 struct node{ int x, next; }tree[maxn << 1]; int head[maxn], son[maxn], fa[maxn], dep[maxn], top[maxn]; int id[maxn], tv[maxn], v[maxn], t[maxn<<2], lazy[maxn<<2], size[maxn], cnt, tla, mmod; void add(int x,int y){ tree[++cnt].x = y; tree[cnt].next = head[x]; head[x] = cnt; } void pushup(int rt){t[rt] = (t[rt<<1] + t[rt<<1|1]) % mmod;} void build(int l, int r, int rt){ if(l == r) t[rt] = tv[l] % mmod; else{ int m = (l + r)>>1; build(l, m, rt<<1); build(m + 1, r, rt<<1|1); pushup(rt); } } void pushdown(int rt, int lenl, int lenr){ if(lazy[rt]){ int r1 = rt<<1, r2 = rt<<1|1; lazy[r1] = (lazy[r1] + lazy[rt]) % mmod; lazy[r2] = (lazy[r2] + lazy[rt]) % mmod; t[r1] = (t[r1] + lenl*lazy[rt]) % mmod; t[r2] = (t[r2] + lenr*lazy[rt]) % mmod; lazy[rt]=0; } } void update(int L, int R, int k, int l, int r, int rt){ if(L <= l && r <= R){ lazy[rt] = (lazy[rt] + k) % mmod; t[rt] = (t[rt] + k*(r-l+1)) % mmod; return; } int m = (l+r)>>1; pushdown(rt, m - l + 1, r - m); if(L <= m) update(L, R, k, l, m, rt<<1); if(R > m) update(L, R, k, m + 1, r, rt<<1|1); pushup(rt); } int query(int L, int R, int l, int r, int rt){ if(L <= l && r <= R) return t[rt] % mmod; int m = (l + r)>>1; pushdown(rt, m - l + 1, r - m); int ans = 0; if(L <= m) ans += query(L, R, l, m, rt<<1); if(R > m) ans += query(L, R, m + 1, r, rt<<1|1); return ans % mmod; } void dfs1(int x, int f, int d){ fa[x] = f; dep[x] = d; size[x] = 1; int mmax = -1; for(int y = head[x]; ~y; y = tree[y].next){ int k = tree[y].x; if(k == f) continue; dfs1(k, x, d + 1); size[x] += size[k]; if(size[k] > mmax){ mmax = size[k]; son[x] = k; } } } void dfs2(int x, int topf){ top[x] = topf; id[x] = ++tla; tv[tla] = v[x]; if(!son[x]) return; dfs2(son[x], topf); for(int y = head[x]; ~y; y = tree[y].next){ int k = tree[y].x; if(k == fa[x] || k == son[x]) continue; dfs2(k, k); } } void uprange(int x, int y, int z){ z %= mmod; while(top[x] != top[y]){ if(dep[top[x]] < dep[top[y]]) swap(x, y); update(id[top[x]], id[x], z, 1, tla, 1); x = fa[top[x]]; } if(dep[x] > dep[y]) swap(x, y); update(id[x], id[y], z, 1, tla, 1); } int qrange(int x, int y){ int ans = 0; while(top[x] != top[y]){ if(dep[top[x]] < dep[top[y]]) swap(x, y); ans=(ans + query(id[top[x]], id[x], 1, tla, 1)) % mmod; x = fa[top[x]]; } if(dep[x] > dep[y]) swap(x, y); return (ans + query(id[x], id[y], 1, tla, 1)) % mmod; } void upson(int x, int z){ z %= mmod; update(id[x], id[x] + size[x] - 1, z, 1, tla, 1); } int qson(int x){ return query(id[x], id[x] + size[x] - 1, 1, tla, 1); } int main(){ int i, n, root, m, x, y, z, flag; cin >> n >> m >> root >> mmod; for(i = 1; i <= n; i++) cin >> v[i]; memset(head, -1, sizeof(head)); for(i = 1; i < n; i++){ cin >> x >> y; add(x, y),add(y, x); } dfs1(root, 0, 1); dfs2(root, root); build(1, tla, 1); for(i = 1; i <= m; i++){ cin >> flag; if(flag == 1){ cin >> x >> y >> z; uprange(x, y, z); }else if(flag == 2){ cin >> x >> y; cout << qrange(x,y) << endl; }else if(flag == 3){ cin >> x >> z; upson(x, z); }else{ cin >> x; cout << qson(x) << endl; } } return 0;} // 树链剖分就是将叶子到子树的根节点的沿途结点这条链,维护成线段树。 //再将子数结点作为叶子,重复此操作。 //最后等于将树分割为若干条链,这样可以通过线段树维护区间。
相关文章推荐
- ACM模板 数据结构
- (模板题)sdut 3402 数据结构实验之排序五:归并求逆序数(归并排序)
- 自备ACM模板-图论篇
- 程序设计竞赛(acm)常用数据结构
- 前缀式计算 ACM 数据结构
- 数据结构图文解析之:二叉堆详解及C++模板实现
- <sdut-ACM>数据结构实验之串三:KMP应用
- 自备ACM模板-其他技巧
- acm 统计字符数 题目很好 自己没有思路 数据结构不清晰 参考了答案
- 模板-数据结构
- Pku acm 3253 Fence Repair 数据结构题目解题报告(一) ----哈夫曼数
- ACM第五次比赛题目及标准程序(数据结构基础)
- 数据结构——划分树模板
- 括号配对问题 ACM 数据结构
- (模板题)sdut 2125 数据结构实验之串二:字符串匹配(KMP)
- CUGB专题训练之数据结构:E - Keywords Search(HDU 2222 AC自动机经典入门模板题)
- 数据结构图文解析之:AVL树详解及C++模板实现
- 数据结构(2)单链表 c++ 模板实现
- <sdut-ACM>数据结构实验之链表六:有序链表的建立
- 数据结构--栈(C语言代码模板及其应用)