尺取
尺取的时候一定要满足"单调性",就是
单调性就是 比如 区间取和 我在右边界向右延伸的过程中 整个区间和是不断增大的 不会变小 不然右侧就不会延伸 反而右边会向回收缩,这样的话就会造成一种很混乱的局面
JES读一本书,要看完所有的知识点,这本书共有P页,第i页恰好有一个知识点ai,(每一个知识点都有一个整数编号)。全书同一个知识点可能会被提到多次,他希望阅读其中一些连续的页把所有知识点都读到,给定每页所读到的知识点,求最少的阅读页数 .
Input
Output
输出最少阅读页数 。
Sample Input
5 1 8 8 8 1
Sample Output
2
这个题就是尺取的时候用map标记一下个数就行
set有去重的作用
#include<iostream> #include<algorithm> #include<set> #include<cstring> #include<map> using namespace std; const int maxn=1e6+100; int a[maxn]; int main(){ int n; while(~scanf("%d",&n)){ set<int>se; map<int,int>mp; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); se.insert(a[i]); } int nn=se.size(); int l=1,r=1; int s=0; int ans=1e9; while(1){ while(r<=n&&s<nn){ if(mp[a[r]]==0){ s++; } mp[a[r]]++; r++; } if(s<nn){ break; } ans=min(ans,r-l); mp[a[l]]--; if(mp[a[l]]==0){ s--; } l++; } printf("%d\n",ans); } }
Input
多组用例,每组用例第一行两个整数n和m分别表示数列长度和查询次数,第二行为n个整数表示数列,第三行为m个整数表示目标数,以n=k=0结束输入 0<=t<=1000000000;1<=n<=100000Output
对于每次查询,输出三个整数sum,l,r,分别表示其绝对值与目标数之差最小的连续序列值与此连续序列的左右端点Sample Input
5 1 -10 -5 0 5 10 3 10 2 -9 8 -7 6 -5 4 -3 2 -1 0 5 11 15 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 15 100 0 0
Sample Output
5 4 4 5 2 8 9 1 1 15 1 15 15 1 15
这个题直接尺取的话不行,因为他不满足单调性,所以要找一个前缀和
#include<iostream> #include<algorithm> using namespace std; const int maxn=1e6+100; int v[maxn]; struct node{ int sum; int id; }a[maxn]; bool cmp(node x,node y){ return x.sum<y.sum; } int main(){ int n,m; while(cin>>n>>m){ if(n+m==0){ break; } a[0].sum=a[0].id=0; for(int i=1;i<=n;i++){ cin>>v[i]; a[i].sum=a[i-1].sum+v[i]; a[i].id=i; } sort(a,a+n+1,cmp); int k; for(int i=1;i<=m;i++){ scanf("%d",&k); int l=0; int r=1; int mi=0x3f3f3f3f; int ans,ansl,ansr; while(r<=n){ int sub=a[r].sum-a[l].sum;//这里是前缀和所以后面要加一 if(abs(sub-k)<mi){ mi=abs(sub-k); ansl=min(a[l].id,a[r].id)+1; ansr=max(a[l].id,a[r].id); ans=sub; } if(sub<k){ r++; } else if(sub>k){ l++; } else{ break; } if(l==r){ r++; } } cout<<ans<<" "<<ansl<<" "<<ansr<<endl; } } }
我们都知道数字是个好玩意,那么我们想知道一个数字能是否能用若干个(或许是一个)连续的素数之和表示,并且想知道有多少种方法。例如,53 有两种表示方法 5 + 7 + 11 + 13 + 17 和 53。 现在给你一个整数 n,你要告诉他这个数字有多少种不同的连续素数和表示方式。Input多组数据输入,每行一个数字 n,当 n=0 时结束。 n 在 2 与 10000之间。Output每个输出占一行,输出对应的答案。Sample Input
2 3 17 41 20 666 12 53 0
Sample Output
1 1 2 3 0 0 1 2
这个还行打个标就行
#include<iostream> #include<algorithm> using namespace std; const int maxn=1e4+100; int prime[maxn]; int biaoji[maxn]; int vis[1000001]; int sum[maxn]; int cnt=0; void inint(){ for(int i=2;i<maxn;i++){ if(!biaoji[i]) prime[++cnt]=i; for(int j=1;j<=cnt&&i*prime[j]<maxn;j++){ biaoji[i*prime[j]]=1; if(i%prime[j]==0){ break; } } } } int main(){ inint(); for(int i=1;i<=cnt;i++){ sum[i]=sum[i-1]+prime[i]; } for(int i=0;i<=cnt;i++){ for(int j=i+1;j<=cnt;j++){ int t=sum[j]-sum[i]; if(t<maxn) vis[t]++; } } int n; while(cin>>n&&n){ cout<<vis[n]<<endl; } }
sj学姐发现自己的裙子上有一个由n个数组成的数组,恰巧sj学姐的幸运数字是s,sj学姐想求出总和不小于s的子数组长度的最小值,但sj学姐太忙了,帮sj学姐解决这个问题。
Input
第一行输入n和s,第二行输入n个正整数。
Output
找到满足要求的子数组的最小长度,如果没有,输出0。
Sample Input
2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5
Sample Output
2
3
#include<iostream> #include<algorithm> using namespace std; const int maxn=1e6+100; int a[maxn]; int main(){ int t,n,m; cin>>t; while(t--){ cin>>n>>m; for(int i=1;i<=n;i++){ cin>>a[i]; } int l=1; int r=1; int sum=0; int ans=0x3f3f3f3f; while(1){ while(sum<m&&r<=n){ sum+=a[r]; r++; } if(sum<m){ break; } ans=min(ans,(r-l)); sum-=a[l]; l++; } if(ans>n){ ans=0; } cout<<ans<<endl; } }
月光女神是创界山最美的守护神。暗黑达垂涎女神的美色。不择手段想要得到女神的芳心!月光女神不堪其扰。干脆设立了一个结界。只有拥有大智慧的人才能通过结界去见女神一面。暗黑达虽然力量强大无比,但脑子不好使,他一直也没能见到女神。现在你能帮小渡见到女神么?
结界给出一个数n。你要求一段连续的数,这些数的平方和等于n。Input输入一个整数n,1<=n<=10^14;Output输出一个数k,k为解的个数。接下来的k行为解,每一行的解要先输出这个解中包含的数字个数,然后从小到大输出解中包含的数字。解的输出顺序要按照所包含的数字个数降序排列。Sample Input
2030
Sample Output
2
4 21 22 23 24
3 25 26 27
满足2030的解有2个 第一个解包含4个数 分别是 21 22 23 24。21^2+22^2+23^2+24^2=2030。
第二个解包含3个数 分别是 25 26 27。25^2+26^2+27^2=2030。
这个直接尺取就行
#include<iostream> #include<algorithm> #include<math.h> using namespace std; typedef long long ll; const int maxn=1e6+100; ll k; int LL[maxn],RR[maxn]; int main(){ while(~scanf("%lld",&k)){ ll l=1,r=1; ll len=sqrt(k*1.0)+1; ll sum=0; int cnt=0; while(l<=len){ while(r<=len&&sum<k){ sum+=r*r; r++; } if(sum==k){ LL[++cnt]=l; RR[cnt]=r-1; } sum-=l*l; l++; } cout<<cnt<<endl; for(int i=1;i<=cnt;i++){ printf("%d ",RR[i]-LL[i]+1); for(int j=LL[i];j<=RR[i];j++){ printf("%d ",j); } cout<<endl; } } }
传送门
有包含n个数的序列a,求能找到最长的区间包含不超过k个不同的元素。Input
第一行包含两个整数 n, k (1 ≤ k ≤ n ≤ 5·105)
第二行包含 n个整数ai (0 ≤ ai ≤ 106) —代表数组 a中的元素.
Output
输出两个整数l, r (1 ≤ l ≤ r ≤ n) — 代表最长区间的左端点和右端点。如果有多个答案,输出任意一组即可。a中元素的位置从1到n进行编号。
Examples
5 5
1 2 3 4 5
1 5
9 3
6 5 1 2 3 2 1 4 5
3 7
3 1
1 2 3
1 1
#include<iostream> #include<algorithm> #include<set> #include<map> using namespace std; const int maxn=1e6+100; int a[maxn]; int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ map<int,int>mp; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } int l=1,r=0; int LL,RR; int num=0; int ans=-1; while(1){ while(r<=n&&num<=m){ r++; if(mp[a[r]]==0){ num++; } mp[a[r]]++; } if((r-l+1)>ans){ ans=(r-l+1); LL=l; RR=r; } if(num<=m){ break; } mp[a[l]]--; if(mp[a[l]]==0){ num--; } l++; } cout<<LL<<" "<<RR-1<<endl; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现