Trie树
高效的存储和查找字符串集合的数据结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <bits/stdc++.h> using namespace std; const int N = 100010; int son[N][26], cnt[N], idx; char str[N]; void insert(char str[]) { int p=0; for(int i=0;str[i];i++) { int u=str[i]-'a'; if(!son[p][u]) son[p][u]= ++idx; p=son[p][u]; } cnt[p]++; } int query(char str[]) { int p=0; for(int i=0;str[i];i++) { int u=str[i]-'a'; if(!son[p][u]) return 0; p=son[p][u]; } return cnt[p]; } int main() { int n; scanf("%d",&n); while(n--) { char op[2]; scanf("%s%s",op,str); if(op[0]=='I') insert(str); else printf("%d\n",query(str)); } return 0; }
|
并查集
并查集:
1、将两个元素合并
2、询问两个元素是否在一个集合当中
基本原理:每个集合用一棵树来表示。树根的编号就是整个集合的编号。每个节点存储它的父节点,p[x]表示x的父节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include <bits/stdc++.h> using namespace std; const int N = 100010; int n,m; int p[N];
int find(int x) { if(p[x]!=x) p[x]=find(p[x]); return p[x]; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) p[i]=i; while(m--) { char op[2]; int a,b; scanf("%s%d%d",op,&a,&b); if(op[0]=='M') p[find(a)]=find(b); else { if(find(a)==find(b)) put("Yes"); else puts("No"); } } return 0; }
|
连通块中点的数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <bits/stdc++.h> using namespace std; const int N = 100010; int n,m; int p[N], size[N];
int find(int x) { if(p[x]!=x) p[x]=find(p[x]); return p[x]; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { p[i]=i; size[i]=1; } while(m--) { char op[5]; int a,b; scanf("%s",op); if(op[0]=='C') { scanf("%d%d",&a,&b); if(find(a)==find(b)) continue; size[find(b)]+=size[find(a)]; p[find(a)]=find(b); } else if(op[1]=='1') { scanf("%d%d",&a,&b); if(find(a)==find(b)) puts("Yes"); else puts("No"); } else { scanf("%d",&a); printf("%d\n",size[find(a)]); } } return 0; }
|
堆
- 插入一个数 heap[++size]=x;up(size);
- 求集合当中的最小值 heap[1];
- 删除最小值 heap[1]=heap[size];size–;down(1);
- 删除任意一个元素 heap[k]=heap[size];size–;down(k);up(k);
- 修改任意一个元素 heap[k]=x;down(k);up(k);
堆的结构:
堆是一个完全二叉树
堆排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <bits/stdc++.h> using namespace std; const int N = 100010; int n,m; int h[N],size; void down(int u) { int t=u; if(u*2<=size && h[u*2]<h[t]) t=u*2; if(u*2+1<=size && h[u*2+1]<h[t]) t=u*2+1; if(u!=t) { swap(h[u],h[t]); down(t); } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&h[i]); size=n; for(int i=n/2;i;i--) down(i); while(m--) { printf("%d", h[1]); h[1]=h[size]; size--; down(1); } return 0; }
|
模拟堆
int strcmp(const char* str1, const char* str2);
strcmp()
函数的比较规则如下:
- 如果
str1
和str2
相等,返回值为0。
- 如果
str1
小于str2
,返回值为负数。
- 如果
str1
大于str2
,返回值为正数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| #include <bits/stdc++.h> using namespace std; const int N = 100010; int h[N], ph[N], hp[N], size; void heap_swap(int a,int b) { swap(ph[hp[a]],ph[hp[b]]); swap(hp[a],hp[b]); swap(h[a],h[b]); } void down(int u) { int t=u; if(u*2<=size && h[u*2]<h[t]) t=u*2; if(u*2+1<=size && h[u*2+1]<h[t]) t=u*2+1; if(u!=t) { heap_swap(u,t); down(t); } } void up(int u) { while(u/2 && h[u/2]>h[u]) { heap_swap(u/2,u); u/=2; } } int main() { int n,m=0; scanf("%d",&n); while(n--) { char op[10]; int k,x; scanf("%s",op); if(!strcmp(op,"I")) { scanf("%d",&x); size++; m++; ph[m]=size, hp[size]=m; h[size]=x; up(size); } else if(!strcmp(op,"PM")) printf("%d\n",h[1]); else if(!strcmp(op,"DM")) { heap_swap(1,size); size--; down(1); } else if(!strcmp(op,"D")) { scanf("%d",&k); k=ph[k]; heap_swap(k,size); size--; down(k),up(k); } else { scanf("%d%d",&k,&x); k=ph[k]; h[k]=x; down(k),up(k); } } return 0; }
|