数据结构
数据结构
链表
单链表
双链表
栈
手写模拟
单调栈
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int stk[maxn], tp;
int n;
int main() {
cin >> n;
int tp = 0;
while(n--)
{
int x; cin>>x;
while (tp && stk[tp] >= x) tp--;
if(tp) cout<<stk[tp]<<' ';
else cout<<-1<<' ';
stk[++tp] = x;
}
}
队列
手写模拟
单调队列
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int n, k;
int g[maxn];
int q[maxn]; int hd, rr; // hd头 rr 尾
int main() {
scanf("%d%d", &n, &k);
for(int i=1; i<=n; i++) scanf("%d", &g[i]);
hd = 0, rr = -1;
for(int i=1; i<=n; i++) {
if (hd <= rr && i - k >= q[hd]) hd++; //判断出窗口
while(hd <= rr && g[q[rr]] >= g[i]) rr--;
q[++rr] = i;
if(i >= k) printf("%d ", g[q[hd]]);
}
puts("");
hd = 0, rr = -1;
for(int i=1; i<=n; i++) {
if (hd <= rr && i - k >= q[hd]) hd++; //判断出窗口
while(hd <= rr && g[q[rr]] <= g[i]) rr--;
q[++rr] = i;
if(i >= k) printf("%d ", g[q[hd]]);
}
}
KMP
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5, M = 1e6+5;
char p[N], s[M];
int n, m;
int ne[N];
int main() {
cin>>n>>p+1>>m>>s+1;
ne[1] = 0;
for(int i=2, j=0; i<=n ; i++) {
while(j && p[i] != p[j+1]) j = ne[j];
if(p[i] == p[j+1]) j++;
ne[i] = j;
}
for(int i=1, j=0; i<=m; i++) {
while(j && s[i] != p[j+1]) j = ne[j];
if(s[i] == p[j+1]) j++;
if(j == n) {
cout<<i - n<<' ';
}
}
}
Trie
维护一个字符串集合,支持两种操作:
“I x”向集合中插入一个字符串x;
“Q x”询问一个字符串在集合中出现了多少次。
#include <bits/stdc++.h>
using namespace std;
const int maxl = 1e5+5;
int trie[maxl][26], cct[maxl], idx;
int n;
char str[maxl];
int insert (char str[]) {
int p = 0;
for(int i=0; str[i]; i++) {
int c = str[i] - 'a';
if(!trie[p][c]) trie[p][c] = idx++;
p = trie[p][c];
}
cct[p] ++;
}
int query (char str[]) {
int p = 0;
for(int i=0; str[i]; i++) {
int c = str[i] - 'a';
if(!trie[p][c]) return 0;
p = trie[p][c];
}
return cct[p];
}
int main (){
cin>>n; idx = 1;
while(n--) {
string CMD;
cin>>CMD>>str;
if(CMD == "I") insert(str);
else cout<<query(str)<<endl;
}
}
并查集
朴素并查集
带路径压缩的并查集
int find(int x) {
if(g[x] != x) g[x] = find(g[x]);
return g[x];
}
维护一些特殊属性的并查集
食物链
int find(int x) {
if (p[x] != x) {
int u = find(p[x]); //找到父亲
d[x] += d[p[x]]; //此时父亲的距离已经被更新
p[x] = u;
}
return p[x];
}
堆
手写堆
#include <iostream>
using namespace std;
const int maxn = 1e5+5;
int heap[maxn], hp[maxn], ph[maxn], idx, sz, n;
void heap_swap(int a, int b)
{
swap(ph[hp[a]], ph[hp[b]]);
swap(hp[a], hp[b]);
swap(heap[a], heap[b]);
}
void down(int t)
{
int u = t;
if(2 * t <= sz && heap[2*t] < heap[u]) u = 2 * t;
if(2 * t + 1 <= sz && heap[2*t+1] < heap[u]) u = 2 * t + 1;
if(u != t) {
heap_swap(u, t);
down(u);
}
}
void up(int t)
{
while(t/2 && heap[t/2] > heap[t]) heap_swap(t/2, t), t /= 2;
}
int main() {
cin >> n;
while(n--) {
string p; cin>>p;
if(p == "I") {
int x; cin >> x;
heap[++sz] = x;
hp[sz] = ++idx;
ph[idx] = sz;
up(sz);
}
if(p == "PM") {
cout << heap[1] <<endl;
}
if(p == "DM") {
heap_swap(1, sz);
sz--;
down(1);
}
if(p == "D") {
int k; cin >> k;
k = ph[k];
heap_swap(sz, k);
sz--;
down(k), up(k);
}
if(p == "C") {
int k, x; cin>>k>>x;
heap[ph[k]] = x;
down(ph[k]);
up(ph[k]);
}
}
}
堆排序
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int n, m, sz;
int g[maxn];
void down(int u) {
int t = u;
if(2 * u <= sz && g[2 * u] < g[t]) t = 2 * u;
if(2 * u + 1 <= sz && g[2 * u + 1] < g[t]) t = 2 * u + 1 ;
if(u != t) {
swap(g[u], g[t]);
down(t);
}
}
int main() {
cin>> n >> m;
for(int i=1 ;i<=n; i++) cin>>g[i];
sz = n;
for(int i=n/2; i; i--) down(i);
for(int i=1; i<=m; i++) {
cout<<g[1]<<' ';
g[1] = g[sz]; sz--;
down(1);
}
}
哈希表
模拟散列表
字符串哈希
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int md = 131, maxn = 1e5+5; //131 or 13331
ULL p[maxn], h[maxn]; //h哈希,p存2^
int n, m;
ULL query(int l, int r) {
return h[r] - h[l-1] * p[r-l+1];//
}
int main() {
p[0] = 1;
cin >> n >> m;
char str[maxn]; cin>>str+1;
for(int i=1; i<=n; i++) {
p[i] = p[i-1] * md;
h[i] = h[i-1] * md + str[i];
}
while(m--){
int l1, r1, l2, r2; cin>>l1>>r1>>l2>>r2;
if(query(l1, r1) == query(l2, r2)) cout<<"Yes"<<endl;
else cout << "No"<<endl;
}
}

浙公网安备 33010602011771号