当前位置: 首页 > news >正文

2025年大一ACM训练-尺取

2025年大一ACM训练-尺取

​​尺取法(Sliding Window):

​​1. 基本概念​​
  尺取法(又称滑动窗口法)是一种​​通过维护窗口的左右边界来高效解决子区间问题​​的算法技巧,常用于:
  1.寻找满足条件的​​最短/最长连续子数组​​
  2.统计满足某些性质的子区间数量
时间复杂度通常从暴力 O(n²) 优化到 O(n)
​​2. 算法框架​

int left = 0, right = 0;  // 初始化窗口边界
while (right < n) {// 1. 扩大右边界,将a[right]加入窗口update(window, a[right]);right++;// 2. 满足条件时,收缩左边界while (is_valid(window)) {// 更新答案(如最小长度)ans = min(ans, right - left);// 移除a[left]并移动左边界remove(window, a[left]);left++;}
}

  视频讲解见下方

尺取法

Problem A:尺取Language
和 Problem G:尺取 Jessica Reading Problem
Problem F:林大实验林场–尺取法
是同一个
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int a[1000005];
int main()
{int t,n,s,i,j=0,k=0,sum=0,c;unordered_set<int>set;scanf("%d",&n);for(i=0;i<n; i++){scanf("%d",&a[i]);set.insert(a[i]);}j=set.size();unordered_map<int,int>map;   //不能使用std::mapint l=0,r=0,ans=1000005;while(r<n){if(map[a[r]]==0) sum++;map[a[r]]++;r++;while(sum==j){ans=min(ans,r-l);map[a[l]]--;if(map[a[l]]==0) sum--;l++;}}printf("%d\n",ans);return 0;
}

  标准尺取法的应用(寻找最短区间问题),但本题要注意使用std::unordered_map。以下是二者区别:
  为什么 std::map 比 std::unordered_map 慢?​​
std::map 和 std::unordered_map 都是 C++ STL 提供的关联容器,用于存储键值对(key-value),但它们的底层实现不同,导致时间复杂度不同:
在这里插入图片描述

Problem B:尺取-Graveyard Design
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector <pair<ll,ll> > ans;
bool compare(const pair<ll,ll>& a,const pair<ll,ll>& b)
{return (a.second - a.first) > (b.second - b.first);
}
int main()
{ll n;scanf("%lld",&n);ll l=1,r=1,sum=0;while(1){while(sum<n){sum+=r*r;r++;}if(sum<n) break;if(sum==n) ans.push_back(make_pair(l,r-1));sum-=l*l;l++;if(l*l>n) break;}sort(ans.begin(),ans.end(),compare);printf("%lld\n",ans.size());for(ll i=0;i<ans.size();i++){printf("%lld ",ans[i].second-ans[i].first+1);for(ll j=ans[i].first;j<=ans[i].second;j++){printf("%lld ",j);  //每一个都要加空格 }printf("\n");}return 0;
}

Problem C:尺取-Sum of Consecutive Prime Numbers
在这里插入图片描述

  先用埃氏筛求出素数队列,然后在素数队列下进行尺取法

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn = 1e4+10;
int primeNum[maxn];
bool isPrime[maxn];
void getPrime(int n)
{for(int i=0;i<maxn;i++) isPrime[i]=true;for(int i=2;i<=n;i++)if(isPrime[i])for(int j=2;i*j<=n;j++) isPrime[i*j]=false;for(int i=2,j=1;i<=n;i++)if(isPrime[i]) primeNum[j++] = i;
}
int main()
{int n;getPrime(maxn-10);while(cin >> n && n){int cnt=0,i=1,j=1,sum=0;if(isPrime[n]) cnt++;while(1){while(sum<n && primeNum[j]<n) sum+=primeNum[j++];if(sum<n) break;if(sum==n) cnt++;sum-=primeNum[i++];}cout<<cnt<<endl;}return 0;
}

Problem D:尺取-序列
在这里插入图片描述

  标准尺取题

#include<bits/stdc++.h>
using namespace std;
int m,n,s;
int q[100005];
int main()
{scanf("%d",&m);while(m--){scanf("%d%d",&n,&s);for(int i=0;i<n;i++) scanf("%d",&q[i]);int l=0,r=0,ans=n+1,sum=0;while(1){while(r<n && sum<s) sum+=q[r++];if(sum<s) break;ans=min(ans,r-l);sum-=q[l++];}if(ans==n+1) printf("0\n");else printf("%d\n",ans);}return 0;
}

Problem E:尺取-字符串
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std; 
const int N = 1e6 + 5;
char s[N];
int cnt[255];
int main()
{int i, j, n, m, tot = 0, ans = 1e9;scanf("%s",s+1);n = strlen(s+1);j = 1; cnt[s[1]]++; tot = 1;for(i = 2; i <= n; i++){if(!cnt[s[i]]) tot++;cnt[s[i]]++;while(cnt[s[j]]>1){cnt[s[j]]--;j++;}if(tot==26) ans=min(ans,i-j+1);}printf("%d",ans);return 0;
}

  尺取法相关问题均与上述模板相似
                                —ending

相关文章:

  • 代码随想录算法训练营 Day61 图论ⅩⅠ Floyd A※ 最短路径算法
  • methods的实现原理
  • Chainlink:连接 Web2 与 Web3 的去中心化桥梁
  • iOS 使用CocoaPods 添加Alamofire 提示错误的问题
  • 【Docker 新手入门指南】第十四章:Docker常用命令
  • HTML5实现简洁的端午节节日网站源码
  • 电子电路:深入了解4013D触发器的机制和原理
  • 设计模式之简单工厂模式
  • OSG编译wasm尝试
  • LVS-NAT 负载均衡群集
  • PHP7内核剖析 学习笔记 第九章 PHP基础语法的实现
  • 51. N-Queens
  • 【达梦】达梦数据库使用TypeHandler读取数据库时,将字段中的数据读取为数组
  • 用 Python 模拟雪花飘落效果
  • 【从零开始学习QT】快捷键、帮助文档、Qt窗口坐标体系
  • 集成均衡功能电池保护芯片在大功率移动电源的应用,创芯微CM1341-DAT、杰华特JW3312、赛微微电CW1244、中颖SH366006
  • 25平航杯复现
  • java队列
  • 通义灵码2.5——基于MCP打造我的12306火车票智能查询小助手
  • 人工智能在智能城市中的创新应用与未来趋势
  • 网站推广建设加盟/网络营销与管理
  • h5设计是什么/杭州百家号优化
  • 绍兴做网站的/最近一周新闻大事件
  • 自己做网站做什么内容/百度seo优化推广公司
  • 给公司做企业网站/软文推广发稿
  • 大连网站优化/seo诊断工具网站