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 }
View Code
复制代码

 

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 }
View Code
复制代码

【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 }
View Code
复制代码

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 }
View Code
复制代码

【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 }
View Code
复制代码

 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 }
View Code
复制代码

 【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 }
View Code
复制代码

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 }
View Code
复制代码

【 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 }
View Code
复制代码

【 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 }
View Code
复制代码

【 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 }
View Code
复制代码

5前缀和与差分

【5.1】一维前缀和

1 cin>>a[i];
2 sum[i]=sum[i-1]+a[i];
View Code

【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 }
View Code
复制代码

【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 }
View Code
复制代码

【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 }
View Code
复制代码

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 }
View Code
复制代码

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 }
View Code
复制代码

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 }
View Code
复制代码

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 }
View Code
复制代码

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 }
View Code
复制代码

 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 }
View Code
复制代码

 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 }
View Code
复制代码

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 }
View Code
复制代码

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 }
View Code
复制代码

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 }
View Code
复制代码

【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 }
View Code
复制代码

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 }
View Code
复制代码

 

【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 }
View Code
复制代码

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 }
View Code
复制代码

【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 }
View Code
复制代码
复制代码
 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 }
View Code
复制代码

 【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 }
View Code
复制代码

 

posted @   may0113  阅读(271)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示