# 临阵摸鱼
# 注意
无脑 longlong
# 读数据
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N = 1e4+10; |
| int a[N]; |
| int main(){ |
| int n; cin >> n; |
| int cnt = 0; |
| while(scanf("%d", &a[cnt]) != EOF) cnt++; |
| sort(a, a+cnt); |
| int ans1, ans2; |
| for(int i = 1; i < cnt; i++) { |
| if(a[i] - a[i-1] > 1) ans1 = a[i-1]+1; |
| if(a[i] == a[i-1]) ans2 = a[i]; |
| } |
| cout << ans1 << ' ' << ans2; |
| return 0; |
| } |
| #include<bits/stdc++.h> |
| using namespace std; |
| int a[100010]; |
| bool cmp(int a, int b){return a>b;} |
| int main(){ |
| int n,m; cin>>n>>m; |
| for(int i=1;i<=n;i++) a[i]=i; |
| while(m--){ |
| int p,q; scanf("%d%d",&p,&q); |
| if(p==1) sort(a+q,a+n+1); |
| if(p==0) sort(a+1,a+q+1,cmp); |
| } |
| for(int i=1;i<=n;i++) printf("%d ",a[i]); |
| return 0; |
| } |
# 读字符
cin 不能读空格,getline 可以
# 数字位数处理
| while(x){ |
| int b = x % 10; |
| x /= 10; |
| } |
# 日期处理
注意输出格式,用 printf %02d
| for(int year=2000;year<=2022;year++) |
| for(int month=1;month<=12;month++) |
| for(int day=1;day<=31;day++) |
| { |
| if(month == 1 || month == 3 || month == 5 || month == 7 || |
| month == 8 || month == 10 || month == 12); |
| else if(month == 2) |
| { |
| if((year%4==0&&year%100!=0) || year % 400 == 0) |
| { |
| if(day > 29) break; |
| } |
| else |
| { |
| if(day > 28) break; |
| } |
| } |
| else |
| { |
| if(day > 30) break; |
| } |
| } |
| #include <bits/stdc++.h> |
| using namespace std; |
| |
| int m1[] = {0, 1, 3, 5, 7, 8, 10, 12}; |
| int m2[] = {0, 4, 6, 9, 11}; |
| |
| int main() { |
| int year = 2014, month = 11, day = 9; |
| |
| for (int i = 1; i <= 1000; i++) { |
| day++; |
| |
| for (int j = 1; j <= 7; j++) { |
| if (month == m1[j] && day == 32) { |
| month++; |
| day = 1; |
| break; |
| } |
| } |
| |
| for (int j = 1; j <= 4; j++) { |
| if (month == m2[j] && day == 31) { |
| month++; |
| day = 1; |
| break; |
| } |
| } |
| |
| if (month == 2) { |
| if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { |
| if (day == 30) { |
| month++; |
| day = 1; |
| } |
| } else { |
| if (day == 29) { |
| month++; |
| day = 1; |
| } |
| } |
| } |
| |
| if (month == 13) { |
| month = 1; |
| year++; |
| } |
| } |
| |
| cout << year << "-" << month << "-" << day; |
| |
| return 0; |
| } |
| #include <bits/stdc++.h> |
| using namespace std; |
| int main(){ |
| int mon[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; |
| int y=2014,d=9,m=11,w; |
| for(w=0;w<1000;w++){ |
| if((y%4==0&&y%100!=0)||(y%400==0)) mon[2]=29; |
| else mon[2]=28; |
| d++; |
| if(d>mon[m]){ |
| d=1; |
| m++; |
| } |
| if(m>12){ |
| y++; |
| m=1; |
| } |
| } |
| printf("%04d-%02d-%02d",y,m,d); |
| return 0; |
| } |
# 高精度
| #include <bits/stdc++.h> |
| using namespace std; |
| string add(string a,string b){ |
| string s; |
| int c = 0; |
| for(int i=a.size()-1,j=b.size()-1;i>=0||j>=0||c>0;i--,j--){ |
| if(i>=0) c += a[i]-'0'; |
| if(j>=0) c += b[j]- '0'; |
| s += (c%10)+ '0'; |
| c /= 10; |
| } |
| reverse(s.begin(),s.end()); |
| return s; |
| } |
| int main(){ |
| string a,b; cin>>a>>b; |
| cout<<add(a,b); |
| return 0; |
| } |
# stl
list
| 1 |
| 2 list<int>node; |
| 3 |
| 4 for(int i=1;i<=n;i++) |
| 5 node.push_back(i); |
| 6 |
| 7 list<int>::iterator it = node.begin(); |
| 8 while(node.size()>1){ |
| 9 it++; |
| 10 if(it == node.end()) |
| 11 it = node.begin(); |
| 12 } |
| 13 |
| 14 list<int>::iterator next = ++it; |
| 15 if(next==node.end()) next=node.begin(); |
| 16 node.erase(--it); |
| 17 it = next; |
| 18 |
stack
queue
priority
pair
| pair<int,int> pos; |
| pos.first = 1; |
| pos.second = 1; |
| a = make_pair(1,1); |
| a = pair<int,int>(1,1); |
# 结构体排序
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 struct stu{ |
| 4 int id; |
| 5 int c,m,e; |
| 6 int sum; |
| 7 }st[305]; |
| 8 bool cmp(stu a,stu b){ |
| 9 if(a.sum > b.sum) return True; |
| 10 else if(a.sum < b.sum) return False; |
| 11 else{ |
| 12 if(a.c > b.c) return True; |
| 13 else if(a.c < b.c) return False; |
| 14 else{ |
| 15 if(a.id > b.id) return False; |
| 16 else return True; |
| 17 } |
| 18 } |
| 19 } |
| 20 int main(){ |
| 21 int n; cin>>n; |
| 22 for(int i=1;i<=n;i++){ |
| 23 st[i].id = i; |
| 24 cin >> st[i].c >> st[i].m >> st[i].e; |
| 25 st[i].sum = st[i].c + st[i].m + st[i].e; |
| 26 } |
| 27 sort(st+1,st+1+n,cmp); |
| 28 for(int i=1;i<=5;i++) cout<<st[i].id<<’ ‘<<st[i].sum<<”\n”; |
| 29 return 0; |
| 30 } |
# 双指针
| #include <bits/stdc++.h> |
| using namespace std; |
| |
| int a[100010]; |
| |
| int main(){ |
| int n, S; |
| cin >> n >> S; |
| |
| for (int i = 0; i < n; ++i) { |
| cin >> a[i]; |
| } |
| |
| int sum = 0, ans = 1e8; |
| |
| for (int i = 0, j = 0; i < n;) { |
| if (sum < S) { |
| sum += a[i]; |
| i++; |
| } else { |
| ans = min(i - j, ans); |
| sum -= a[j]; |
| j++; |
| } |
| } |
| |
| if (ans == 1e8) { |
| cout << 0; |
| } else { |
| cout << ans; |
| } |
| |
| return 0; |
| } |
# dfs
如果搜索所有的路径,应该用 DFS;如果只搜索最短的路径,则应该用 BFS。
搜索所有路径
| 1 ans; |
| 2 void dfs(层数,其他参数){ |
| 3 if (出局判断){ |
| 4 更新答案; |
| 5 return; |
| 6 } |
| 7 (剪枝) |
| 8 for (枚举下一层可能的情况) |
| 9 if (used[i] == 0) { |
| 10 used[i] = 1; |
| 11 dfs(层数+1,其他参数); |
| 12 used[i] = 0; |
| 13 } |
| 14 return; |
| 15 } |
# 全排列
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 int a[20]={1,2,3,4,5,6,7,8,9,10,11,12,13}; |
| 4 bool vis[20]; |
| 5 int b[20]; |
| 6 void dfs(int s,int t){ |
| 7 if(s==t) { |
| 8 for(int i=0; i<t; ++i) cout<<b[i]<< “ “; |
| 9 cout<<”; “; |
| 10 return; |
| 11 } |
| 12 for(int i=0;i<t;i++) |
| 13 if(!vis[i]){ |
| 14 vis[i]=True; |
| 15 b[s]=a[i]; |
| 16 dfs(s+1,t); |
| 17 vis[i]=False; |
| 18 } |
| 19 } |
| 20 int main(){ |
| 21 int n=3; |
| 22 dfs(0,n); |
| 23 return 0; |
| 24 } |
# 组合
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 int a[]={1,2,3,4,5,6,7,8,9,10}; |
| 4 int vis[10]; |
| 5 void dfs(int k) { |
| 6 if (k == 3) { |
| 7 for(int i=0;i<3;i++) |
| 8 if(vis[i]) cout<<a[i]; |
| 9 cout<<”-”; |
| 10 } |
| 11 else { |
| 12 vis[k] = 0; |
| 13 dfs(k + 1); |
| 14 vis[k] = 1; |
| 15 dfs(k + 1); |
| 16 } |
| 17 } |
| 18 int main() { |
| 19 dfs(0); |
| 20 return 0; |
| 21 } |
# bfs
| #include <bits/stdc++.h> |
| using namespace std; |
| |
| struct node{ |
| int x, y; |
| string path; |
| }; |
| |
| char mp[31][51]; |
| char k[4] = {'D', 'L', 'R', 'U'}; |
| int dir[4][2] = <!--swig0-->; |
| int vis[30][50]; |
| |
| void bfs(){ |
| node start; |
| start.x = 0; start.y = 0; start.path = ""; |
| vis[0][0] = 1; |
| queue<node> q; |
| q.push(start); |
| while(!q.empty()){ |
| node now = q.front(); q.pop(); |
| if(now.x == 29 && now.y == 49){ |
| cout << now.path; |
| return; |
| } |
| for(int i = 0; i < 4; i++){ |
| node next; |
| next.x = now.x + dir[i][0]; |
| next.y = now.y + dir[i][1]; |
| if(next.x < 0 || next.x >= 30 || next.y < 0 || next.y >= 50) continue; |
| if(vis[next.x][next.y] == 1 || mp[next.x][next.y] == '1') |
| continue; |
| vis[next.x][next.y] = 1; |
| next.path = now.path + k[i]; |
| q.push(next); |
| } |
| } |
| } |
| |
| int main(){ |
| for(int i = 0; i < 30; i++) cin >> mp[i]; |
| bfs(); |
| return 0; |
| } |
# 连通性
dfs
(1) 从图上任意一个点 u 开始遍历,标记点 u 已经被搜索过。
(2) 递归点 u 的所有符合连通条件的邻居点。
(3) 递归结束,找到了与点 u 连通的所有点,这是一个连通块。
(4) 不与点 u 连通的、其他没有访问到的点,继续用上述步骤处理,直到找到所有的连通块。
bfs
(1) 从图上任意一个点 u 开始遍历,把它放进队列中。
(2) 弹出队首 u,标记点 u 已经被搜索过,然后搜索点 u 的邻居点,即与点 u 连通的点,将其放到队列中。
(3) 弹出队首,标记为已被搜索过,然后搜索与它连通的邻居点,放进队列。
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N = 1010; |
| char mp[N][N]; |
| int vis[N][N]; |
| int d[4][2] = <!--swig1-->; |
| int flag; |
| void bfs(int x, int y) { |
| queue<pair<int, int>> q; |
| q.push({x, y}); |
| vis[x][y] = 1; |
| while (q.size()) { |
| pair<int, int> t = q.front(); |
| q.pop(); |
| int tx = t.first, ty = t.second; |
| if( mp[tx][ty+1]== '#' && mp[tx][ty-1]== '#' && |
| mp[tx+1][ty]== '#' && mp[tx-1][ty]== '#' ) |
| flag = 1; |
| for (int i = 0; i < 4; i++) { |
| int nx = tx + d[i][0], ny = ty + d[i][1]; |
| if(vis[nx][ny]==0 && mp[nx][ny]== '#'){ |
| vis[nx][ny] = 1; |
| q.push({nx, ny}); |
| } |
| } |
| } |
| } |
| int main() { |
| int n; cin >> n; |
| for (int i = 0; i < n; i++) cin >> mp[i]; |
| int ans = 0; |
| for (int i = 0; i < n; i++) |
| for (int j = 0; j < n; j++) |
| if (mp[i][j] == '#' && vis[i][j]==0) { |
| flag = 0; |
| bfs(i, j); |
| if(flag == 0) |
| ans++; |
| } |
| cout << ans << endl; |
| return 0; |
| } |
| |
| |
| |
| */ |
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N = 1010; |
| char mp[N][N]; |
| int vis[N][N]={0}; |
| int d[4][2] = <!--swig2-->; |
| int flag; |
| void dfs(int x, int y){ |
| vis[x][y] = 1; |
| if( mp[x][y+1]== '#' && mp[x][y-1]== '#' && |
| mp[x+1][y]== '#' && mp[x-1][y]== '#' ) |
| flag = 1; |
| for(int i = 0; i < 4; i++){ |
| int nx = x + d[i][0], ny = y + d[i][1]; |
| if(vis[nx][ny]==0 && mp[nx][ny]== '#') |
| dfs(nx,ny); |
| } |
| } |
| int main(){ |
| int n; cin >> n; |
| for (int i = 0; i < n; i++) cin >> mp[i]; |
| int ans = 0 ; |
| for(int i = 0; i < n; i++) |
| for(int j = 0; j < n; j++) |
| if(mp[i][j]== '#' && vis[i][j]==0){ |
| flag = 0; |
| dfs(i,j); |
| if(flag == 0) ans++; |
| } |
| cout<<ans<<endl; |
| return 0; |
| } |
# 剪枝
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 const int N=15; |
| 4 int n, m; |
| 5 int a[N][N], vis[N][N]; |
| 6 int sum, ans=100000; |
| 7 int d[4][2] = { {1,0},{0,-1},{0,1},{-1,0} }; |
| 8 void dfs(int x, int y, int c, int s) { |
| 9 if (2*s>sum) return; |
| 10 if (2*s==sum) { |
| 11 if (c<ans && vis[0][0]) ans = c; |
| 12 return; |
| 13 } |
| 14 vis[x][y]=1; |
| 15 for (int k=0; k<4; k++) { |
| 16 int tx=x+d[k][0], ty=y+d[k][1]; |
| 17 if (tx>=0 && tx<n && ty>=0 && ty<m && !vis[tx][ty]) |
| 18 dfs(tx,ty,c+1,s+a[x][y]); |
| 19 } |
| 20 vis[x][y]=0; |
| 21 } |
| 22 int main() { |
| 23 cin>>m>>n; |
| 24 for (int i=0; i<n; i++) |
| 25 for (int j=0; j<m; j++) |
| 26 cin>>a[i][j], sum+=a[i][j]; |
| 27 dfs(0,0,0,0); |
| 28 cout<<(ans==100000 ? 0 : ans); |
| 29 return 0; |
| 30 } |
# 二分
| bool check(int x) |
| { |
| |
| } |
| |
| int binarySearch() |
| { |
| int l = 1, r = n; |
| while (r - l > 1) |
| { |
| int mid = (l + r) >> 1; |
| if (check(mid)) |
| r = mid; |
| else |
| l = mid; |
| } |
| if (check(l)) |
| return l; |
| else if (check(r)) |
| return r; |
| return -1; |
| } |
# 区间最值
| 1 #include <bits/stdc++.h> |
| 2 using namespace std; |
| 3 int main(){ |
| 4 int a[7] = {5,7,1,2,3,6,9}; |
| 5 int id = min_element(a+2, a+5) - a; |
| 6 cout<<a[id]<< “\n”; |
| 7 id = max_element(a+2, a+5) - a; |
| 8 cout<<a[id]<< “\n”; |
| 9 int s = accumulate(a+2, a+5,0); |
| 10 cout<<s<<”\n”; |
| 11 return 0; |
| 12 } |
# st
| 1 #include <bits/stdc++.h> |
| 2 using namespace std; |
| 3 const int N = 500001; |
| 4 int n,m; |
| 5 int a[N],dp[N][40]; |
| 6 void st_init(){ |
| 7 for(int i=1;i<=n;i++) dp[i][0] = a[i]; |
| 8 int p = (int)(log(double(n)) / log(2.0)); |
| 9 for(int k=1;k<=p;k++) |
| 10 for(int s=1;s+(1<<k)<=n+1;s++) |
| 11 dp[s][k]=max(dp[s][k−1], dp[s+(1<<(k-1))][k-1]); |
| 12 } |
| 13 int st_query(int L,int R){ |
| 14 int k = (int)(log(double(R-L+1)) / log(2.0)); |
| 15 return max(dp[L][k],dp[R-(1<<k)+1][k]); |
| 16 } |
| 17 int main(){ |
| 18 scanf(“%d%d”,&n,&m); |
| 19 for(int i=1;i<=n;i++) scanf(“%d”,&a[i]); |
| 20 st_init(); |
| 21 for(int i=1;i<=m;i++){ |
| 22 int L,R; scanf(“%d%d”,&L,&R); |
| 23 printf(“%d\n”,st_query(L,R)); |
| 24 } |
| 25 return 0; |
| 26 } |
# 前缀和
| 1 #include <bits/stdc++.h> |
| 2 using namespace std; |
| 3 int a[11]={0,4,5,6,7,8,9,10,11,12,13}; |
| 4 int sum[11]={0}; |
| 5 int main (){ |
| 6 |
| 7 sum[1]=a[1]; |
| 8 for(int i =2;i<=10;i++) sum[i] = a[i]+ sum[i-1]; |
| 9 |
| 10 cout << “sum[]=”; |
| 11 for(int i =1;i<=10;i++) cout<<sum[i]<< “ “; cout <<”\n”; |
| 12 |
| 13 cout << “ a[]=” << a[1]<< “ “; |
| 14 for(int i =2;i<=10;i++) cout << sum[i] - sum[i-1]<< “ “; |
| 15 |
| 16 cout << “\n”<< “ [5,8]= “<<sum[8]-sum[4]; |
| 17 return 0; |
| 18 } |
# 二维前缀和
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 int s[550][550]; |
| 4 int main(){ |
| 5 int n,m,k; cin>>n>>m>>k; |
| 6 for(int i=1;i<=n;i++) |
| 7 for(int j=1;j<=m;j++){ |
| 8 int v; scanf(“%d”,&v); |
| 9 s[i][j] = s[i-1][j]+s[i][j-1]-s[i-1][j-1]+v; |
| 10 } |
| 11 long long ans = 0; |
| 12 for(int i1=1;i1<=n;i1++) |
| 13 for(int i2=i1;i2<=n;i2++) |
| 14 for(int j1=1; j1<=m; j1++) |
| 15 for(int j2=j1; j2<=m; j2++) { |
| 16 int z = s[i2][j2]-s[i2][j1-1]-s[i1-1][j2]+s[i1-1][j1-1]; |
| 17 if(z<=k) ans++; |
| 18 } |
| 19 cout<<ans; |
| 20 } |
# 一维差分
| for(int i=1;i<=n;i++) |
| d[i]=a[i]-a[i-1]; |
| #include <bits/stdc++.h> |
| using namespace std; |
| |
| const int MAXN = 100005; |
| |
| int n, m, a[MAXN], d[MAXN], sumd[MAXN]; |
| |
| int main() { |
| cin >> n >> m; |
| |
| |
| for (int i = 1; i <= n; i++) { |
| cin >> a[i]; |
| d[i] = a[i] - a[i - 1]; |
| } |
| |
| |
| for (int i = 1; i <= m; i++) { |
| int l, r, c; |
| cin >> l >> r >> c; |
| d[l] += c; |
| d[r + 1] -= c; |
| } |
| |
| |
| for (int i = 1; i <= n; i++) { |
| sumd[i] = sumd[i - 1] + d[i]; |
| cout << sumd[i] << " "; |
| } |
| |
| return 0; |
| } |
# 并差集
| 1 #include <bits/stdc++.h> |
| 2 using namespace std; |
| 3 const int N = 8e5+5; |
| 4 int s[N]; |
| 5 void init_set(){ |
| 6 for(int i=1; i<=N; i++) s[i] = i; |
| 7 } |
| 8 int find_set(int x){ |
| 9 |
| 10 |
| 11 return x==s[x]? x:find_set(s[x]); |
| 12 } |
| 13 void merge_set(int x, int y){ |
| 14 x = find_set(x); |
| 15 y = find_set(y); |
| 16 if(x != y) s[x] = s[y]; |
| 17 } |
| 18 int main (){ |
| 19 init_set(); |
| 20 int n,m; cin>>n>>m; |
| 21 while(m--){ |
| 22 int op,x,y; cin>>op>>x>>y; |
| 23 if(op == 1) merge_set(x, y); |
| 24 if(op == 2){ |
| 25 if(find_set(x)==find_set(y)) cout << “YES”<<endl; |
| 26 else cout << “NO”<<endl; |
| 27 } |
| 28 } |
| 29 return 0; |
| 30 } |
| 1 #include <bits/stdc++.h> |
| 2 using namespace std; |
| 3 const int N=1e5+100; |
| 4 vector<int> edge[N]; |
| 5 int s[N],vis[N],ring[N]; |
| 6 int start,flag; |
| 7 int tot; |
| 8 void init_set(){ |
| 9 for(int i=1;i<=N;i++) s[i]=i; |
| 10 } |
| 11 int find_set(int x){ |
| 12 if(x!=s[x]) s[x]=find_set(s[x]); |
| 13 return s[x]; |
| 14 } |
| 15 void merge_set(int x,int y){ |
| 16 int tmp = x; |
| 17 x = find_set(x); |
| 18 y = find_set(y); |
| 19 if(x!=y) s[y]=s[x]; |
| 20 else start = tmp; |
| 21 } |
| 22 void dfs(int x,int step){ |
| 23 if(flag) return; |
| 24 if(x==start) |
| 25 if(vis[x]==1){ |
| 26 tot = step-1; |
| 27 flag = 1; |
| 28 return ; |
| 29 } |
| 30 ring[step] = x; |
| 31 for(int i=0;i<edge[x].size();i++){ |
| 32 int y=edge[x][i]; |
| 33 if(!vis[y]){ |
| 34 vis[y]=1; |
| 35 dfs(y,step+1); |
| 36 vis[y]=0; |
| 37 } |
| 38 } |
| 39 } |
| 40 int main(){ |
| 41 int n; scanf(“%d”,&n); |
| 42 init_set(); |
| 43 for(int i=1;i<=n;i++) { |
| 44 int u,v; scanf(“%d %d”,&u,&v); |
| 45 edge[u].push_back(v); edge[v].push_back(u); |
| 46 merge_set(u,v); |
| 47 } |
| 48 flag = 0; |
| 49 dfs(start,1); |
| 50 sort(ring+1,ring+1+tot); |
| 51 for(int i=1;i<=tot;i++) printf(“%d “,ring[i]); |
| 52 return 0; |
| 53 } |
# 树状数组
处理动态前缀和 nlogn
| 1 #define lowbit(x) ((x) & - (x)) |
| 2 int tree[N]; |
| 3 void update(int x, int d) { |
| 4 while(x <= N) { |
| 5 tree[x] += d; |
| 6 x += lowbit(x); |
| 7 } |
| 8 } |
| 9 int sum(int x) { |
| 10 int ans = 0; |
| 11 while(x > 0){ |
| 12 ans += tree[x]; |
| 13 x -= lowbit(x); |
| 14 } |
| 15 return ans; |
| 16 } |
| 1 #include <bits/stdc++.h> |
| 2 using namespace std; |
| 3 const int N = 1000; |
| 4 #define lowbit(x) ((x) & - (x)) |
| 5 int tree[N]={0}; |
| 6 void update(int x, int d) { |
| 7 while(x <= N) { |
| 8 tree[x] += d; |
| 9 x += lowbit(x); |
| 10 } |
| 11 } |
| 12 int sum(int x) { |
| 13 int ans = 0; |
| 14 while(x > 0){ |
| 15 ans += tree[x]; |
| 16 x -= lowbit(x); |
| 17 } |
| 18 return ans; |
| 19 } |
| 20 |
| 21 int a[11]={0,4,5,6,7,8,9,10,11,12,13}; |
| 22 int main (){ |
| 23 |
| 24 for(int i=1;i<=10;i++) update(i,a[i]); |
| 25 |
| 26 cout << “old: [5,8] = “<<sum(8)-sum(4)<< “\n”; |
| 27 |
| 28 update(5,100); |
| 29 |
| 30 cout << “new: [5,8] = “<<sum(8)-sum(4); |
| 31 return 0; |
| 32 } |
# 线段树
区间查询问题(最值、区间和)是线段树的一个基本应用场景。
| 1 void push_up(int p){ |
| 2 |
| 3 tree[p] = max(tree[ls(p)], tree[rs(p)]); |
| 4 } |
| 5 void build(int p,int pl,int pr){ |
| 6 if(pl==pr){ |
| 7 tree[p] = -INF; |
| 8 return; |
| 9 } |
| 10 int mid = (pl+pr) >> 1; |
| 11 build(ls(p),pl,mid); |
| 12 build(rs(p),mid+1,pr); |
| 13 push_up(p); |
| 14 } |
| 1 void update(int p,int pl,int pr,int L,int R,int d){ |
| 2 if(L<=pl && pr<=R){ |
| 3 tree[p] = d; |
| 4 return; |
| 5 } |
| 6 int mid=(pl+pr)>>1; |
| 7 if(L<=mid) update(ls(p),pl,mid,L,R,d); |
| 8 if(R>mid) update(rs(p),mid+1,pr,L,R,d); |
| 9 push_up(p); |
| 10 return; |
| 11 } |
| 1 int query(int p,int pl,int pr,int L,int R){ |
| 2 int res = -INF; |
| 3 if (L<=pl && pr<=R) return tree[p]; |
| 4 int mid=(pl+pr)>>1; |
| 5 if (L<=mid) res = max(res, query(ls(p),pl,mid,L,R)); |
| 6 if (R>mid) res = max(res, query(rs(p),mid+1,pr,L,R)); |
| 7 return res; |
| 8 } |
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 const int N = 200001; |
| 4 const int INF = 0X7FFFFFFF; |
| 5 int ls(int p){ return p<<1; } |
| 6 int rs(int p){ return p<<1|1;} |
| 7 int tree[N<<2]; |
| 8 void push_up(int p){ |
| 9 |
| 10 tree[p] = max(tree[ls(p)], tree[rs(p)]); |
| 11 } |
| 12 void build(int p,int pl,int pr){ |
| 13 if(pl==pr){ |
| 14 tree[p] = -INF; |
| 15 return; |
| 16 } |
| 17 int mid = (pl+pr) >> 1; |
| 18 build(ls(p),pl,mid); |
| 19 build(rs(p),mid+1,pr); |
| 20 push_up(p); |
| 21 } |
| 22 void update(int p,int pl,int pr,int L,int R,int d){ |
| 23 if(L<=pl && pr<=R){ |
| 24 tree[p] = d; |
| 25 return; |
| 26 } |
| 27 int mid=(pl+pr)>>1; |
| 28 if(L<=mid) update(ls(p),pl,mid,L,R,d); |
| 29 if(R>mid) update(rs(p),mid+1,pr,L,R,d); |
| 30 push_up(p); |
| 31 return; |
| 32 } |
| 33 int query(int p,int pl,int pr,int L,int R){ |
| 34 int res = -INF; |
| 35 if (L<=pl && pr<=R) return tree[p]; |
| 36 int mid=(pl+pr)>>1; |
| 37 if (L<=mid) res = max(res, query(ls(p),pl,mid,L,R)); |
| 38 if (R>mid) res = max(res, query(rs(p),mid+1,pr,L,R)); |
| 39 return res; |
| 40 } |
| 41 int main (){ |
| 42 int t=0,cnt=0,m,D; |
| 43 scanf (“%d%d”,&m,&D); |
| 44 build(1,1,N); |
| 45 for (int b=1;b<=m;++b){ |
| 46 char c[2]; int x; scanf (“%s %d”,c,&x); |
| 47 if (c[0]==’A’){ |
| 48 cnt++; |
| 49 update(1,1,N,cnt,cnt,(x+t)%D); |
| 50 } |
| 51 else { |
| 52 t = query(1,1,N,cnt-x+1,cnt); |
| 53 printf (“%d\n”,t); |
| 54 } |
| 55 } |
| 56 return 0; |
| 57 } |
# 动态规划
01
memset (dp,0,sizeof (dp)); // 清 0。这一行可以不写,因为全局静态数组自动初始化为 0
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N = 3011; |
| int w[N], c[N]; |
| int dp[N][N]; |
| int solve(int n, int C){ |
| for(int i=1; i<=n; i++) |
| for(int j=0; j<=C; j++){ |
| if(c[i]>j) dp[i][j]=dp[i-1][j]; |
| else dp[i][j]=max(dp[i-1][j], dp[i-1][j-c[i]]+w[i]); |
| } |
| return dp[n][C]; |
| } |
| int main(){ |
| int n,C; cin>>n>>C; |
| for(int i=1;i<=n;i++) cin>>c[i]>>w[i]; |
| memset(dp,0,sizeof(dp)); |
| cout << solve(n, C); |
| return 0; |
| } |
自上而下用带记忆化搜索的递归代码,自下而上用递推代码
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 const int N = 3011; |
| 4 int w[N], c[N]; |
| 5 int dp[N][N]; |
| 6 int solve(int i, int j){ |
| 7 if (dp[i][j] != 0) return dp[i][j]; |
| 8 if(i == 0) return 0; |
| 9 if(c[i] > j) dp[i][j] = solve(i-1,j); |
| 10 else dp[i][j] = max(solve(i-1,j), solve(i-1,j-c[i])+w[i]); |
| 11 return dp[i][j] ; |
| 12 } |
| 13 int main(){ |
| 14 int n,C; cin >> n >> C; |
| 15 for(int i=1;i<=n;i++) cin >>c[i] >> w[i]; |
| 16 memset(dp,0,sizeof(dp)); |
| 17 cout << solve(n, C) << endl; |
| 18 return 0; |
| 19 } |
滚动数组
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 const int N = 3011; |
| 4 int w[N], c[N]; |
| 5 int dp[2][N]; |
| 6 int solve(int n, int C){ |
| 7 int now = 0, old = 1; |
| 8 for(int i=1; i<=n; i++){ |
| 9 swap(old,now); |
| 10 for(int j = 0; j <= C; j++){ |
| 11 if(c[i] > j) dp[now][j] = dp[old][j]; |
| 12 else dp[now][j] = max(dp[old][j], dp[old][j-c[i]]+w[i]); |
| 13 } |
| 14 } |
| 15 return dp[now][C]; |
| 16 } |
| 17 int main(){ |
| 18 int n,C; cin >> n >> C; |
| 19 for(int i=1;i<=n;i++) cin >> c[i] >> w[i]; |
| 20 memset(dp,0,sizeof(dp)); |
| 21 cout << solve(n, C) << endl; |
| 22 return 0; |
| 23 } |
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 const int N = 3011; |
| 4 int w[N], c[N]; |
| 5 int dp[N]; |
| 6 int solve(int n, int C){ |
| 7 for(int i=1; i<=n; i++) |
| 8 for(int j=C; j>=c[i]; j--) |
| 9 dp[j] = max(dp[j],dp[j-c[i]]+w[i]); |
| 10 return dp[C]; |
| 11 } |
| 12 int main(){ |
| 13 int n,C; cin >> n >> C; |
| 14 for(int i=1;i<=n;i++) cin >> c[i] >> w[i]; |
| 15 memset(dp,0,sizeof(dp)); |
| 16 cout << solve(n, C) << endl; |
| 17 return 0; |
| 18 } |
最大重量
dp[j]
表示背包容量为 j 时,可以装入的物品的最大重量。状态转移方程为 dp[j] = max(dp[j], dp[j-w[i]] + w[i])
,表示当前背包容量为 j 时,要么不装入第 i 个物品( dp[j]
),要么装入第 i 个物品( dp[j-w[i]] + w[i]
)。这里选择最大值,表示要装入尽可能多的物品。
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 int dp[20010]; |
| 4 int w[40]; |
| 5 int main(){ |
| 6 int V,n; scanf(“%d%d”,&V,&n); |
| 7 for(int i=1;i<=n;i++) scanf(“%d”,&w[i]); |
| 8 for(int i=1; i<=n; i++) |
| 9 for(int j=V; j>=w[i]; j--) |
| 10 dp[j] =max(dp[j], dp[j-w[i]]+w[i]); |
| 11 printf(“%d\n”,V-dp[V]); |
| 12 } |
01 方案数
背包容量为 2022,物品体积为 1~2022,往背包中装 10 个物品,要求总体积为 2022,问一共有多少种方案。与标准 0/1 背包问题的区别是这一题是求方案总数。
定义 dp [][][],dp [i] [j] [k] 表示从数字 1~i 取 j 个和为 k 的方案数。
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 long long dp[2222][11][2222]={0}; |
| 4 int main(){ |
| 5 for(int i=0;i<=2022;i++) dp[i][0][0]=1; |
| 6 for(int i=1;i<=2022;i++) |
| 7 for(int j=1;j<=10;j++) |
| 8 for(int k=1;k<=2022;k++){ |
| 9 if(k<i) dp[i][j][k] = dp[i-1][j][k]; |
| 10 else dp[i][j][k] = dp[i-1][j][k]+dp[i-1][j-1][k-i]; |
| 11 } |
| 12 cout << dp[2022][10][2022]; |
| 13 return 0; |
| 14 } |
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 long long dp[11][2222]; |
| 4 int main(){ |
| 5 dp[0][0]=1; |
| 6 for(int i=1;i<=2022;i++) |
| 7 for(int j=10;j>=1;j--) |
| 8 for(int k=i;k<=2022;k++) |
| 9 dp[j][k]+=dp[j-1][k-i]; |
| 10 cout << dp[10][2022]; |
| 11 return 0; |
| 12 } |
完全 bag
| 1 #include<bits/stdc++.h> |
| 2 using namespace std; |
| 3 const int N = 3011; |
| 4 int w[N], c[N]; |
| 5 int dp[N][N]; |
| 6 int solve(int n, int C){ |
| 7 for (int i = 1; i <= n; i++) { |
| 8 for (int j = C; j >= 0; j--) { |
| 9 if(i==1) dp[i][j] = 0; |
| 10 else dp[i][j] = dp[i - 1][j]; |
| 11 for (int k = 0; k * c[i] <= j; k++) |
| 12 dp[i][j] = max(dp[i][j], dp[i - 1][j - k * c[i]] + k * w[i]); |
| 13 } |
| 14 } |
| 15 return dp[n][C]; |
| 16 } |
| 17 int main(){ |
| 18 int n,C; cin >> n >> C; |
| 19 for(int i=1;i<=n;i++) cin >> c[i] >> w[i]; |
| 20 memset(dp,0,sizeof(dp)); |
| 21 cout << solve(n, C) << endl; |
| 22 return 0; |
| 23 } |
最长公共子序列
# string
| #include<bits/stdc++.h> |
| using namespace std; |
| int main(){ |
| string str ="123456789abcdefghiaklmn"; |
| for(int i=0;i<10;i++) cout<<str[i]<< " "; |
| cout << endl; |
| |
| cout<<"1()23的位置: "<<str.find("123")<<endl; |
| cout<<"34在str[2]到str[n-1]中的位置: "<<str.find("34",2)<<endl; |
| |
| cout<<"ab在str[0]到str[12]中的位置: "<<str.rfind("ab",12)<<endl; |
| |
| |
| cout<<"str[3]及以后的子串: "<<str.substr(3)<<endl; |
| |
| cout<<"从str[2]开始的4个字符: "<<str.substr(2,4)<<endl; |
| |
| |
| str.replace(str.find("a"), 5, "@#"); |
| cout<<str<<endl; |
| |
| str.insert(2, "***"); |
| cout<<"从2号位置插入: "<<str<<endl; |
| |
| str.append("$$$"); |
| cout<<"在字符串str后面添加字符串: "<<str<<endl; |
| |
| cout<<str.size()<<endl; |
| cout<<str.length()<<endl; |
| |
| string str1="aaa",str2="bbb"; |
| swap(str1, str2); |
| cout<<str1<<" "<<str2<<endl; |
| |
| cout<<str1.compare(str2)<<endl; |
| if(str1==str2) cout <<"=="; |
| if(str1!=str2) cout <<"!="; |
| return 0; |
| } |
# KMP
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N = 1e6+5; |
| int Next[N]; |
| void getNext(string p){ |
| Next[0]=0; Next[1]=0; |
| for(int i=1; i < p.size(); i++){ |
| int j = Next[i]; |
| while(j && p[i] != p[j]) |
| j = Next[j]; |
| if(p[i]==p[j]) Next[i+1] = j+1; |
| else Next[i+1] = 0; |
| } |
| } |
| int kmp(string s, string p) { |
| int ans=0; |
| int slen=s.size(), plen=p.size(); |
| int j=0; |
| for(int i=0; i<slen; i++) { |
| while(j && s[i]!=p[j]) |
| j=Next[j]; |
| if(s[i]==p[j]) { |
| j++; |
| ans=max(ans,j); |
| } |
| if(j == plen) { |
| |
| |
| return ans; |
| } |
| } |
| return ans; |
| } |
| int main(){ |
| string s, t; |
| cin >> s >> t; |
| getNext(t); |
| cout<<kmp(s, t); |
| return 0; |
| } |
# 快排
| void quick_sort(int q[], int l, int r) |
| { |
| if (l >= r) return; |
| int i = l - 1, j = r + 1, x = q[l + r >> 1]; |
| while (i < j) |
| { |
| do i ++ ; while (q[i] < x); |
| do j -- ; while (q[j] > x); |
| if (i < j) swap(q[i], q[j]); |
| } |
| quick_sort(q, l, j), quick_sort(q, j + 1, r); |
| } |
# 分治
# 进制转换
| #include <iostream> |
| #include <string> |
| #include <algorithm> |
| |
| using namespace std; |
| |
| long long s, base; |
| string p = "0123456789ABCDEF"; |
| string ans; |
| |
| int main() { |
| |
| cin >> s >> base; |
| |
| |
| while (s) { |
| |
| ans.push_back(p[s % base]); |
| |
| s /= base; |
| } |
| |
| |
| reverse(ans.begin(), ans.end()); |
| |
| |
| cout << ans; |
| |
| return 0; |
| } |
| #include <iostream> |
| #include <string> |
| #include <cmath> |
| |
| using namespace std; |
| |
| int main() { |
| string s; |
| long long base = 0, ans = 0, k = 0; |
| |
| |
| cin >> s >> base; |
| |
| |
| for (int i = s.size() - 1; i >= 0; i--) { |
| |
| if (s[i] >= 'A') { |
| ans += (s[i] - 'A' + 10) * pow(base, k++); |
| } else { |
| ans += (s[i] - '0') * pow(base, k++); |
| } |
| } |
| |
| |
| cout << ans; |
| |
| return 0; |
| } |
# 快速幂
| #define ll long long |
| |
| |
| ll qpow(ll a, ll b, ll p) { |
| ll res = 1 % p; |
| |
| while (b) { |
| if (b % 2 == 1) { |
| res = (res % p) * (a % p) % p; |
| } |
| |
| a = (a % p) * (a % p) % p; |
| b /= 2; |
| } |
| |
| return res; |
| } |
# 质数
| #include <cmath> |
| |
| |
| bool isprime(int i) { |
| if (i < 2) |
| return false; |
| |
| for (int j = 2; j <= sqrt(i); j++) { |
| if (i % j == 0) |
| return false; |
| } |
| |
| return true; |
| } |
| const int N = 1000000; |
| |
| int primes[N], cnt; |
| bool f[N]; |
| |
| |
| void get_primes(int n) { |
| for (int i = 2; i <= n; i++) { |
| if (!f[i]) { |
| primes[++cnt] = i; |
| } |
| for (int j = 1; j <= cnt && i * primes[j] <= n; j++) { |
| f[i * primes[j]] = true; |
| if (i % primes[j] == 0) |
| break; |
| } |
| } |
| } |
# gcd
| int gcd(int a, int b) { |
| return b == 0 ? a : gcd(b, a % b); |
| } |
# lcm
两个数的最大公约数 × 最小公倍数 = 两数 相乘
| #include <bits/stdc++.h> |
| using namespace std; |
| |
| |
| long long gcd(long long a, long long b) { |
| if (b == 0) { |
| return a; |
| } |
| return gcd(b, a % b); |
| } |
| |
| int main() { |
| long long a, b; |
| |
| cin >> a >> b; |
| |
| cout << a / gcd(a, b) * b; |
| |
| return 0; |
| } |