ACM比赛前打的板子【重要】
0.开始准备

1 #include<bits/stdc++.h> 2 #pragma GCC optimize("Ofast") 3 using namespace std; 4 #define ll long long 5 #define ull unsigned long long 6 #define endl '\n' 7 const int INF=0x3f3f3f3f; 8 const int N=1e5+5; 9 typedef pair<int,int> PII; 10 int main() 11 { 12 cin.tie(0)->sync_with_stdio(0); 13 14 return 0; 15 }
1.快速排序

1 void quick_sort(int l,int r) 2 { 3 if(l>=r) 4 { 5 return; 6 } 7 int x=q[l+r>>1],i=l-1,j=r+1; 8 while(i<j) 9 { 10 while(q[++i]<x); 11 while(q[--j]>x); 12 if(i<j) 13 swap(q[i],q[j]); 14 } 15 quick_sort(l,j); 16 quick_sort(j+1,r); 17 }
【1.1】基于快排寻找第k小的数

1 int quick_sort(int l,int r,int k) 2 { 3 if(l==r)return q[l]; 4 5 int x=q[l+r>>1],i=l-1,j=r+1; 6 while(i<j) 7 { 8 while(q[++i]<x); 9 while(q[--j]>x); 10 if(i<j) 11 swap(q[i],q[j]); 12 } 13 int s1=j-l+1; 14 if(k<=s1) 15 return quick_sort(l,j,k); 16 17 return quick_sort(j+1,r,k-s1); 18 }
2.归并排序

1 #include<iostream> 2 using namespace std; 3 const int N=1e6+10; 4 int q[N],tmp[N]; 5 int n; 6 7 void merge_sort(int l,int r) 8 { 9 if(l>=r)return; 10 int mid=l+r>>1; 11 merge_sort(l,mid),merge_sort(mid+1,r); 12 int k=0,i=l,j=mid+1; 13 while(i<=mid&&j<=r) 14 if(q[i]<=q[j])tmp[k++]=q[i++]; 15 else tmp[k++]=q[j++]; 16 while(i<=mid)tmp[k++]=q[i++]; 17 while(j<=r)tmp[k++]=q[j++]; 18 19 for(i=l,j=0;i<=r;i++,j++)q[i]=tmp[j]; 20 } 21 int main() 22 { 23 scanf("%d",&n); 24 for(int i=0;i<n;i++) 25 { 26 scanf("%d",&q[i]); 27 } 28 29 merge_sort(0,n-1); 30 31 for(int i=0;i<n;i++) 32 { 33 printf("%d ",q[i]); 34 } 35 return 0; 36 }
【2.1】利用归并排序求逆序对

1 ll merge_sort(int l,int r) 2 { 3 if(l>=r)return 0; 4 int mid=l+r>>1; 5 ll res=merge_sort(l,mid)+merge_sort(mid+1,r); 6 int k=0,i=l,j=mid+1; 7 8 while(i<=mid&&j<=r) 9 { 10 if(q[i]<=q[j]) tmp[k++]=q[i++]; 11 else 12 { 13 tmp[k++]=q[j++]; 14 res+=mid-i+1; 15 } 16 } 17 while(i<=mid)tmp[k++]=q[i++]; 18 while(j<=r)tmp[k++]=q[j++]; 19 for(i=l,j=0;i<=r;i++,j++)q[i]=tmp[j]; 20 return res; 21 }
3.整数二分(数的范围)

1 while(l<r) 2 { 3 int mid=l+r>>1; 4 if(q[mid]>=x) r=mid; 5 else l=mid+1; 6 } 7 if(q[l]!=x)cout<<"-1 -1"<<endl; 8 else 9 { 10 cout<<l<<' '; 11 int l=0,r=n-1; 12 while(l<r) 13 { 14 int mid=l+r+1>>1; 15 if(q[mid]<=x) l=mid; 16 else r=mid-1; 17 } 18 cout<<l<<endl; 19 }
【3.1】浮点数二分(数的三次方根)

1 double bsearch_3(double l, double r) 2 { 3 const double eps = 1e-8; // eps 表示精度,通常比题目多2 4 while (r-l> eps) 5 { 6 double mid = (l + r) / 2; 7 if (check(mid)) r = mid; 8 else l = mid; 9 } 10 return l; 11 }
4高精度
【4.1】高精度加法

1 vector<int> add(vector<int> &A,vector<int> &B) 2 { 3 vector<int> C; 4 5 int t=0; 6 for(int i=0;i<A.size()||i<B.size();i++) 7 { 8 if(i<A.size()) t+=A[i]; 9 if(i<B.size()) t+=B[i]; 10 C.push_back(t%10); 11 t/=10; 12 } 13 if(t) C.push_back(1); 14 return C; 15 } 16 17 int main() 18 { 19 string a,b; 20 vector<int> A,B; 21 cin>>a>>b; 22 for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0'); 23 for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0'); 24 25 auto C=add(A,B); 26 27 for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]); 28 29 return 0; 30 }
【 4.2】高精度减法

1 bool cmp(vector<int>&A,vector<int>&B) 2 { 3 if(A.size()!=B.size()) return A.size()>B.size(); 4 for(int i=A.size()-1;i>=0;i--) 5 if(A[i]!=B[i]) 6 return A[i]>B[i]; 7 return true; 8 } 9 10 vector<int> sub(vector<int>&A,vector<int>&B) 11 { 12 vector<int>C; 13 for(int i=0,t=0;i<A.size();i++) 14 { 15 t=A[i]-t; 16 if(i<B.size()) t-=B[i]; 17 C.push_back((t+10)%10); 18 if(t<0) t=1; 19 else t=0; 20 } 21 while(C.size()>1&&C.back()==0) C.pop_back();//去掉前导0 22 return C; 23 } 24 25 int main() 26 { 27 string a,b; 28 vector<int>A,B; 29 cin>>a>>b; 30 for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0'); 31 for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0'); 32 33 if(cmp(A,B)) 34 { 35 auto C=sub(A,B); 36 for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]); 37 } 38 else 39 { 40 auto C=sub(B,A); 41 printf("-"); 42 for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]); 43 } 44 return 0; 45 }
【 4.3】高精度乘低精度

1 vector<int>mul(vector<int>&A,int b) 2 { 3 vector<int> C; 4 5 int t=0; 6 for(int i=0;i<A.size()||t;i++) 7 { 8 if(i<A.size()) t+=A[i]*b; 9 C.push_back(t%10); 10 t/=10; 11 } 12 while(C.size()>1&&C.back()==0) C.pop_back(); 13 return C; 14 }
【 4.4】高精度除以低精度

1 vector<int>mul(vector<int>&A,int b,int &r) 2 { 3 vector<int>C; 4 r=0; 5 for(int i=A.size()-1;i>=0;i--) 6 { 7 r=r*10+A[i]; 8 C.push_back(r/b); 9 r%=b; 10 } 11 reverse(C.begin(),C.end()); 12 while(C.size()>1&&C.back()==0) C.pop_back(); 13 return C; 14 }
5前缀和与差分
【5.1】一维前缀和

1 cin>>a[i]; 2 sum[i]=sum[i-1]+a[i];
【5.2】二维前缀和

1 const int N=1e3+10; 2 int a[N][N],s[N][N]; 3 int main() 4 { 5 int n,m,q; 6 scanf("%d%d%d",&n,&m,&q); 7 for(int i=1;i<=n;i++) 8 { 9 for(int j=1;j<=m;j++) 10 { 11 scanf("%d",&a[i][j]); 12 s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]; 13 } 14 } 15 while(q--) 16 { 17 int x1,y1,x2,y2; 18 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 19 int ans=s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]; 20 printf("%d\n",ans); 21 } 22 return 0; 23 }
【5.3】一维差分

1 void insert(int l,int r,int c) 2 { 3 b[l]+=c; 4 b[r+1]-=c; 5 } 6 int main() 7 { 8 int n,m; 9 scanf("%d%d",&n,&m); 10 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 11 for(int i=1;i<=n;i++) insert(i,i,a[i]); 12 while(m--) 13 { 14 int l,r,c; 15 scanf("%d%d%d",&l,&r,&c); 16 insert(l,r,c); 17 } 18 for(int i=1;i<=n;i++) 19 { 20 b[i]+=b[i-1]; 21 printf("%d ",b[i]); 22 } 23 return 0; 24 }
【5.4】二维差分

1 #include<iostream> 2 using namespace std; 3 const int N=1010; 4 int n,m,q; 5 int a[N][N],b[N][N]; 6 void insert(int x1,int y1,int x2,int y2,int c) 7 { 8 b[x1][y1]+=c; 9 b[x2+1][y1]-=c; 10 b[x1][y2+1]-=c; 11 b[x2+1][y2+1]+=c; 12 } 13 14 int main() 15 { 16 scanf("%d%d%d",&n,&m,&q); 17 for(int i=1;i<=n;i++) 18 for(int j=1;j<=m;j++) 19 { 20 scanf("%d",&a[i][j]); 21 insert(i,j,i,j,a[i][j]); 22 } 23 24 25 while(q--) 26 { 27 int x1,y1,x2,y2,c; 28 scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c); 29 insert(x1,y1,x2,y2,c); 30 } 31 for(int i=1;i<=n;i++) 32 for(int j=1;j<=m;j++) 33 b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1]; 34 35 for(int i=1;i<=n;i++) 36 { 37 for(int j=1;j<=m;j++) 38 printf("%d ",b[i][j]); 39 puts(""); 40 } 41 42 return 0; 43 }
6双指针算法
【6.1】最长连续不重复子序列

1 for(int i=0,j=0;i<n;i++) 2 { 3 s[a[i]]++; 4 while(s[a[i]]>1) 5 { 6 s[a[j]]--; 7 j++; 8 } 9 10 res=max(res,i-j+1); 11 }
7.位运算
【7.1】二进制中1的个数

1 int lowbit(int x) 2 { 3 return x&-x; 4 } 5 6 int main() 7 { 8 int n; 9 cin>>n; 10 while(n--) 11 { 12 int x; 13 cin>>x; 14 int res=0; 15 while(x) 16 { 17 x-=lowbit(x); 18 res++; 19 } 20 cout<<res<<" "; 21 } 22 return 0; 23 }
8.离散化
【8.1】区间和

1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 5 using namespace std; 6 7 typedef pair<int, int> PII; 8 9 const int N = 300010; 10 11 int n, m; 12 int a[N], s[N]; 13 14 vector<int> alls; 15 vector<PII> add, query; 16 17 int find(int x) 18 { 19 int l = 0, r = alls.size() - 1; 20 while (l < r) 21 { 22 int mid = l + r >> 1; 23 if (alls[mid] >= x) r = mid; 24 else l = mid + 1; 25 } 26 return r + 1; 27 } 28 29 int main() 30 { 31 cin >> n >> m; 32 for (int i = 0; i < n; i ++ ) 33 { 34 int x, c; 35 cin >> x >> c; 36 add.push_back({x, c}); 37 38 alls.push_back(x); 39 } 40 41 for (int i = 0; i < m; i ++ ) 42 { 43 int l, r; 44 cin >> l >> r; 45 query.push_back({l, r}); 46 47 alls.push_back(l); 48 alls.push_back(r); 49 } 50 51 // 去重 52 sort(alls.begin(), alls.end()); 53 alls.erase(unique(alls.begin(), alls.end()), alls.end()); 54 55 // 处理插入 56 for (auto item : add) 57 { 58 int x = find(item.first); 59 a[x] += item.second; 60 } 61 62 // 预处理前缀和 63 for (int i = 1; i <= alls.size(); i ++ ) s[i] = s[i - 1] + a[i]; 64 65 // 处理询问 66 for (auto item : query) 67 { 68 int l = find(item.first), r = find(item.second); 69 cout << s[r] - s[l - 1] << endl; 70 } 71 72 return 0; 73 }
9区间合并
【9.1】区间合并

1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 using namespace std; 5 typedef pair<int,int> PII; 6 vector<PII>segs; 7 int merge(vector<PII>&segs) 8 { 9 int st,ed=-2e9; 10 int cnt=0; 11 for(auto seg:segs) 12 { 13 if(ed<seg.first) 14 { 15 st=seg.first,ed=seg.second; 16 cnt++; 17 } 18 else ed=max(ed,seg.second); 19 } 20 return cnt; 21 } 22 int main() 23 { 24 int n; 25 cin>>n; 26 while(n--) 27 { 28 int l,r; 29 cin>>l>>r; 30 segs.push_back({l,r}); 31 } 32 sort(segs.begin(),segs.end()); 33 cout<<merge(segs)<<endl; 34 return 0; 35 }
10.单链表
【10.1】单链表

1 #include<iostream> 2 using namespace std; 3 const int N=100010; 4 int head,e[N],ne[N],idx; 5 void init() 6 { 7 head=-1; 8 idx=0; 9 } 10 void add_to_head(int x) 11 { 12 e[idx]=x,ne[idx]=head,head=idx++; 13 } 14 void remove(int k) 15 { 16 ne[k]=ne[ne[k]]; 17 } 18 void add(int k,int x) 19 { 20 e[idx]=x,ne[idx]=ne[k],ne[k]=idx++; 21 } 22 int main() 23 { 24 int m; 25 cin>>m; 26 init(); 27 int k,x; 28 char op; 29 while(m--) 30 { 31 cin>>op; 32 if(op=='H') 33 { 34 cin>>x; 35 add_to_head(x); 36 } 37 else if(op=='D') 38 { 39 cin>>k; 40 if(!k) head=ne[head]; 41 else remove(k-1); 42 } 43 else 44 { 45 cin>>k>>x; 46 add(k-1,x); 47 } 48 } 49 for(int i=head;i!=-1;i=ne[i]) cout<<e[i]<<' '; 50 cout<<endl; 51 return 0; 52 }
11.双链表
12.栈
【12.1】表达式求值

1 #include <iostream> 2 #include <stack> 3 #include <string> 4 #include <unordered_map> 5 using namespace std; 6 7 stack<int> num; 8 stack<char> op; 9 10 //优先级表 11 unordered_map<char, int> h{ {'+', 1}, {'-', 1}, {'*',2}, {'/', 2} }; 12 13 14 void eval()//求值 15 { 16 int a = num.top();//第二个操作数 17 num.pop(); 18 19 int b = num.top();//第一个操作数 20 num.pop(); 21 22 char p = op.top();//运算符 23 op.pop(); 24 25 int r = 0;//结果 26 27 //计算结果 28 if (p == '+') r = b + a; 29 if (p == '-') r = b - a; 30 if (p == '*') r = b * a; 31 if (p == '/') r = b / a; 32 33 num.push(r);//结果入栈 34 } 35 36 int main() 37 { 38 string s;//读入表达式 39 cin >> s; 40 41 for (int i = 0; i < s.size(); i++) 42 { 43 if (isdigit(s[i]))//数字入栈 44 { 45 int x = 0, j = i;//计算数字 46 while (j < s.size() && isdigit(s[j])) 47 { 48 x = x * 10 + s[j] - '0'; 49 j++; 50 } 51 num.push(x);//数字入栈 52 i = j - 1; 53 } 54 //左括号无优先级,直接入栈 55 else if (s[i] == '(')//左括号入栈 56 { 57 op.push(s[i]); 58 } 59 //括号特殊,遇到左括号直接入栈,遇到右括号计算括号里面的 60 else if (s[i] == ')')//右括号 61 { 62 while(op.top() != '(')//一直计算到左括号 63 eval(); 64 op.pop();//左括号出栈 65 } 66 else 67 { 68 while (op.size() && h[op.top()] >= h[s[i]])//待入栈运算符优先级低,则先计算 69 eval(); 70 op.push(s[i]);//操作符入栈 71 } 72 } 73 while (op.size()) eval();//剩余的进行计算 74 cout << num.top() << endl;//输出结果 75 return 0; 76 }
13.单调栈
【13.1】单调栈

1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100010; 4 int n,tt,stk[N]; 5 int main() 6 { 7 cin>>n; 8 for(int i=0;i<n;i++) 9 { 10 int x; 11 cin>>x; 12 while(tt&&stk[tt]>=x)tt--; 13 if(tt)cout<<stk[tt]<<" "; 14 else cout<<-1<<" "; 15 stk[++tt]=x; 16 } 17 return 0; 18 }
14.单调队列
【14.1】滑动窗口

1 #include<iostream> 2 using namespace std; 3 const int N=1000010; 4 int a[N],q[N]; 5 int main() 6 { 7 int n,k; 8 scanf("%d%d",&n,&k); 9 for(int i=0;i<n;i++)scanf("%d",&a[i]); 10 int h=0,t=-1; 11 for(int i=0;i<n;i++) 12 { 13 if(h<=t&&i-k+1>q[h])h++;//q[h]不在窗口[i-m+1,i]内,队头出队 14 while(h<=t&&a[q[t]]>=a[i])t--;//当前值>=队尾值,队尾出队 15 q[++t]=i;//下标入队,便于队头出队 16 if(i>=k-1) printf("%d ",a[q[h]]);//使用队头最大值 17 } 18 puts(""); 19 h=0,t=-1; 20 for(int i=0;i<n;i++) 21 { 22 if(h<=t&&i-k+1>q[h])h++; 23 while(h<=t&&a[q[t]]<=a[i])t--; 24 q[++t]=i; 25 if(i>=k-1) printf("%d ",a[q[h]]); 26 } 27 puts(""); 28 return 0; 29 }
15.KMP
【15.1】KMP字符串

1 #include <iostream> 2 using namespace std; 3 const int N = 100010, M = 1000010; 4 int n, m; 5 int ne[N]; 6 char s[M], p[N]; 7 int main() 8 { 9 cin >> n >> p + 1 >> m >> s + 1; 10 for (int i = 2, j = 0; i <= n; i ++ ) 11 { 12 while (j && p[i] != p[j + 1]) j = ne[j]; 13 if (p[i] == p[j + 1]) j ++ ; 14 ne[i] = j; 15 } 16 for (int i = 1, j = 0; i <= m; i ++ ) 17 { 18 while (j && s[i] != p[j + 1]) j = ne[j]; 19 if (s[i] == p[j + 1]) j ++ ; 20 if (j == n) 21 { 22 printf("%d ", i - n); 23 j = ne[j]; 24 } 25 } 26 return 0; 27 }
16.Trie
【16.1】Trie字符串统计

1 #include <iostream> 2 using namespace std; 3 const int N = 100010; 4 int son[N][26], cnt[N], idx; 5 char str[N]; 6 void insert(char *str) 7 { 8 int p = 0; 9 for (int i = 0; str[i]; i ++ ) 10 { 11 int u = str[i] - 'a'; 12 if (!son[p][u]) son[p][u] = ++ idx; 13 p = son[p][u]; 14 } 15 cnt[p] ++ ; 16 } 17 int query(char *str) 18 { 19 int p = 0; 20 for (int i = 0; str[i]; i ++ ) 21 { 22 int u = str[i] - 'a'; 23 if (!son[p][u]) return 0; 24 p = son[p][u]; 25 } 26 return cnt[p]; 27 } 28 int main() 29 { 30 int n; 31 scanf("%d", &n); 32 while (n -- ) 33 { 34 char op[2]; 35 scanf("%s%s", op, str); 36 if (*op == 'I') insert(str); 37 else printf("%d\n", query(str)); 38 } 39 40 return 0; 41 }
【16.2】最大异或树

1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 const int N = 100010, M = 3100010; 5 int n; 6 int a[N], son[M][2], idx; 7 void insert(int x) 8 { 9 int p = 0; 10 for (int i = 30; i >= 0; i -- ) 11 { 12 int &s = son[p][x >> i & 1]; 13 if (!s) s = ++ idx; 14 p = s; 15 } 16 } 17 int search(int x) 18 { 19 int p = 0, res = 0; 20 for (int i = 30; i >= 0; i -- ) 21 { 22 int s = x >> i & 1; 23 if (son[p][!s]) 24 { 25 res += 1 << i; 26 p = son[p][!s]; 27 } 28 else p = son[p][s]; 29 } 30 return res; 31 } 32 int main() 33 { 34 scanf("%d", &n); 35 for (int i = 0; i < n; i ++ ) 36 { 37 scanf("%d", &a[i]); 38 insert(a[i]); 39 } 40 int res = 0; 41 for (int i = 0; i < n; i ++ ) res = max(res, search(a[i])); 42 printf("%d\n", res); 43 return 0; 44 }
17.并查集
【17.1】合并集合

1 #include <iostream> 2 using namespace std; 3 const int N = 100010; 4 int n,m,p[N]; 5 int find(int x)//(核心)【返回x的祖宗节点】+【路径压缩】 6 { 7 if(p[x]!=x)p[x]=find(p[x]);//如果x不是根节点 8 return p[x]; 9 } 10 int main() 11 { 12 cin>>n>>m; 13 for(int i=1;i<=n;i++) p[i]=i;//先把所有的节点的p值赋值成自己 14 while(m--) 15 { 16 char op; 17 int a,b; 18 cin>>op>>a>>b; 19 if(op=='M') p[find(a)]=find(b);//a的父结点是b 20 else 21 { 22 if(find(a)==find(b))puts("Yes"); 23 else puts("No"); 24 } 25 } 26 return 0; 27 }
【17.3】食物链

1 #include <iostream> 2 using namespace std; 3 const int N = 50010; 4 int n,m,p[N],d[N]; 5 int find(int x) 6 { 7 if(p[x]!=x) 8 { 9 10 int t=find(p[x]);//存一下根节点是谁 11 d[x]+=d[p[x]]; 12 p[x]=t; 13 } 14 return p[x]; 15 } 16 int main() 17 { 18 cin>>n>>m; 19 for(int i=1;i<=n;i++) p[i]=i; 20 int res=0; 21 while(m--) 22 { 23 int t,x,y; 24 cin>>t>>x>>y; 25 if(x>n||y>n) res++; 26 else 27 { 28 int px=find(x),py=find(y); 29 if(t==1) 30 { 31 if(px==py&&(d[x]-d[y])%3)res++; 32 else if(px!=py) 33 { 34 p[px]=py; 35 d[px]=d[y]-d[x]; 36 } 37 } 38 else 39 { 40 if(px==py&&(d[x]-d[y]-1)%3)res++; 41 else if(px!=py)//x和y不在一个集合里 42 { 43 p[px]=py; 44 d[px]=d[y]+1-d[x]; 45 } 46 47 } 48 } 49 50 } 51 cout<<res<<endl; 52 return 0; 53 }
18.堆
【18.1】堆排序

1 #include <iostream> 2 using namespace std; 3 const int N = 100010; 4 int n,m; 5 int h[N],cnt; 6 void down(int u) 7 { 8 int t=u; 9 if(u*2<=cnt&&h[u*2]<h[t])t=u*2; 10 if(u*2+1<=cnt&&h[u*2+1]<h[t])t=u*2+1; 11 if(u!=t) 12 { 13 swap(h[u],h[t]);//交换 14 down(t);//递归处理 15 } 16 17 } 18 int main() 19 { 20 cin>>n>>m; 21 for(int i=1;i<=n;i++)cin>>h[i]; 22 cnt=n; 23 for(int i=n/2;i;i--)down(i); 24 while(m--) 25 { 26 cout<<h[1]<<" ";//把堆顶输出出来 27 h[1]=h[cnt]; 28 cnt--; 29 down(1); 30 } 31 return 0; 32 }
【18.2】模拟堆
19.哈希表
【19.1】模拟散列表(拉链法+寻址法)

1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int N=100003;//离十万最近的一个质数 5 int h[N];//开一个槽 6 int e[N],ne[N],idx;//值、下一个位置在什么地方、当前用到的位置 7 8 void insert(int x) 9 { 10 int k=(x%N+N)%N;//目的是让余数变成正数 11 e[idx]=x,ne[idx]=h[k],h[k]=idx++; 12 } 13 14 bool find(int x) 15 { 16 int k=(x%N+N)%N; 17 for(int i=h[k];i!=-1;i=ne[i]) 18 { 19 if(e[i]==x) 20 return true; 21 } 22 return false; 23 } 24 25 int main() 26 { 27 int n; 28 cin>>n; 29 memset(h,-1,sizeof h);//将所有槽清空(空指针用-1表示) 30 while(n--) 31 { 32 char op[2]; 33 int x; 34 cin>>op>>x; 35 if(*op=='I')insert(x); 36 else 37 { 38 if(find(x))cout<<"Yes"<<endl; 39 else cout<<"No"<<endl; 40 } 41 } 42 return 0; 43 }

1 #include<bits/stdc++.h>//开放寻址法 2 using namespace std; 3 const int N=200003,null=0x3f3f3f3f; 4 int h[N]; 5 6 int find(int x) 7 { 8 int k=(x%N+N)%N; 9 while(h[k]!=null &&h[k]!=x)//这个位置有人,并且这个位置不等于x 10 { 11 k++; 12 if(k==N) k=0;//循环看第0个位置 13 } 14 return k; 15 } 16 int main() 17 { 18 int n; 19 cin>>n; 20 memset(h,0x3f,sizeof h); 21 while(n--) 22 { 23 char op[2]; 24 int x; 25 cin>>op>>x; 26 int k=find(x); 27 if(*op=='I') h[k]=x; 28 else 29 { 30 if(h[k]!=null)puts("Yes"); 31 else puts("No"); 32 } 33 } 34 return 0; 35 }
【19.2】字符串哈希

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned long long ULL;//溢出相当于对2的64次方取模 4 const int N=100010,P=131;//P通常取131或者13331 5 int n,m; 6 char str[N]; 7 ULL h[N],p[N]; 8 9 ULL get(int l,int r) 10 { 11 return h[r]-h[l-1]*p[r-l+1];//h[l-1]向r对齐 12 } 13 int main() 14 { 15 cin>>n>>m>>str+1;//字符串从下标1开始储存 16 p[0]=1;//p的零次方为1 17 for(int i=1;i<=n;i++) 18 { 19 p[i]=p[i-1]*P; 20 h[i]=h[i-1]*P+str[i];//前缀和 21 } 22 while(m--)//处理m次询问 23 { 24 int l1,r1,l2,r2; 25 cin>>l1>>r1>>l2>>r2; 26 if(get(l1,r1)==get(l2,r2))puts("Yes"); 27 else puts("No"); 28 } 29 return 0; 30 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现