目的:对给定的一个序列,在序列中寻找包含全部需求的、长度最小的一段子序列。一般用来解决具有单调性的区间问题。

时间复杂度:O(n)

https://blog.csdn.net/lxt_lucia/article/details/81091597

自用模板:

poj3061,给定一个序列,使得其和大于或等于S,求最短的子序列长度。

  1. #include<stdio.h>
  2. #include<iostream>
  3. #define INF 0x3f3f3f3f
  4. using namespace std;
  5. const int maxn=1e5+;
  6. int main()
  7. {
  8. int T;
  9. scanf("%d",&T);
  10. while(T--)
  11. {
  12. int n,s,a[maxn],st=,en=,ans=INF;
  13. long long sum=;
  14. scanf("%d%d",&n,&s);
  15. for(int i=;i<n;i++)scanf("%d",&a[i]);
  16. while()
  17. {
  18. while(en<n&&sum<s)sum+=a[en++];
  19. if(sum<s)break; //如果右端点移动到区间末尾其和还不大于等于S,结束区间的枚举
  20. ans=min(ans,en-st);
  21. sum-=a[st++];
  22. }
  23. if(ans==INF)ans=;
  24. printf("%d\n",ans);
  25. }
  26. return ;
  27. }

poj3320,一本书有P页,每一页都一个知识点,求去最少的连续页数覆盖所有的知识点,使用map来查询次数。

  1. #include<stdio.h>
  2. #include<iostream>
  3. #include<map>
  4. #include<set>
  5. #define INF 0x3f3f3f3f
  6. using namespace std;
  7. const int maxn=1e6+;
  8. map<int,int> mp;
  9. set<int> s;
  10. int main()
  11. {
  12. int n,a[maxn],st=,en=,ans=INF,num,sum=;
  13. scanf("%d",&n);
  14. for(int i=;i<n;i++)scanf("%d",&a[i]),s.insert(a[i]);
  15. num=s.size();
  16. while()
  17. {
  18. while(en<n&&sum<num)
  19. {
  20. if(mp[a[en]]==)sum++;
  21. mp[a[en]]++;
  22. en++;
  23. }
  24. if(sum<num)break;
  25. ans=min(ans,en-st);
  26. mp[a[st]]--;
  27. if(mp[a[st]]==)sum--;
  28. st++;
  29. }
  30. if(ans==INF)ans=;
  31. printf("%d\n",ans);
  32. return ;
  33. }

poj2739,找到某一个区间使得连续和等于某一给定值k。

  1. #include<stdio.h>
  2. #include<iostream>
  3. #define INF 0x3f3f3f3f
  4. using namespace std;
  5. const int maxn=1e5+;
  6. bool prime[maxn];
  7. int p[maxn],tot;
  8. void init()
  9. {
  10. for(int i=;i<;i++)prime[i]=true;
  11. for(int i=;i<;i++)
  12. {
  13. if(prime[i])p[tot++]=i;
  14. for(int j=;j<tot&&i*p[j]<;j++)
  15. {
  16. prime[i*p[j]]=false;
  17. if(i%p[j]==)break;
  18. }
  19. }
  20. }
  21.  
  22. int main()
  23. {
  24. init();
  25. int n;
  26. while(scanf("%d",&n),n!=)
  27. {
  28. int st=,en=,ans=,sum=;
  29. while()
  30. {
  31. while(en<n&&sum<n)sum+=p[en++];
  32. if(sum==n)ans++;
  33. if(st==en)break;
  34. sum-=p[st++];
  35. }
  36. printf("%d\n",ans);
  37. }
  38. return ;
  39. }

poj2100,找到某一个区间使得区间内的数的平方和等于某一给定值k。不加1LL的比较超时了(什么鬼哦),代码二的样式我jio的不错。

  1. #include<stdio.h>
  2. #include<iostream>
  3. #define INF 0x3f3f3f3f
  4. using namespace std;
  5. const int maxn=1e5+;
  6. struct node
  7. {
  8. int l,r;
  9. }p[maxn];
  10. int main()
  11. {
  12. long long n;
  13. scanf("%lld",&n);
  14. int st=,en=,ans=,k=;
  15. long long sum=;
  16. while()
  17. {
  18. while(1ll*en*en<=n&&sum<n)sum+=1ll*en*en,en++;
  19. if(sum==n)ans++,p[k].l=st,p[k++].r=en-;
  20. if(sum<n)break;
  21. sum-=1ll*st*st,st++;
  22. }
  23. printf("%d\n",ans);
  24. for(int i=;i<k;i++)
  25. {
  26. printf("%d ",p[i].r-p[i].l+);
  27. for(int j=p[i].l;j<p[i].r;j++)
  28. printf("%d ",j);
  29. printf("%d\n",p[i].r);
  30. }
  31.  
  32. return ;
  33. }
  1. #include<stdio.h>
  2. #include<iostream>
  3. #define INF 0x3f3f3f3f
  4. using namespace std;
  5. const int maxn=1e5+;
  6. struct node
  7. {
  8. int l,r;
  9. }p[maxn];
  10. int main()
  11. {
  12. long long n,sum=,st=,en=;
  13. int ans=,k=;
  14. scanf("%lld",&n);
  15. while()
  16. {
  17. if(sum==n)ans++,p[k].l=st,p[k++].r=en-;
  18. if(sum>=n)sum-=1ll*st*st,st++;
  19. else
  20. {
  21. if(en*en<=n)sum+=1ll*en*en,en++;
  22. else break;
  23. }
  24. }
  25. printf("%d\n",ans);
  26. for(int i=;i<k;i++)
  27. {
  28. printf("%lld ",p[i].r-p[i].l+);
  29. for(long long j=p[i].l;j<p[i].r;j++)
  30. printf("%lld ",j);
  31. printf("%lld\n",p[i].r);
  32. }
  33.  
  34. return ;
  35. }

uva 11572,求没有重复数字的最长区间。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define INF 0x3f3f3f3f
  4. const int maxn=1e6+;
  5. int a[maxn];
  6. int main()
  7. {
  8. int T;
  9. scanf("%d",&T);
  10. while(T--)
  11. {
  12.  
  13. map<int,int> mp;
  14. int n,ans=,st=,en=,sum=;
  15. scanf("%d",&n);
  16. for(int i=;i<n;i++)scanf("%d",&a[i]);
  17. while()
  18. {
  19. while(en<n)
  20. {
  21. if(mp[a[en]]==)sum++,mp[a[en]]++,en++;
  22. else break;
  23. }
  24. ans=max(ans,en-st);
  25. if(en==n)break;
  26. if(mp[a[st]]==)mp[a[st]]--;
  27. sum--;
  28. st++;
  29. }
  30. printf("%d\n",ans);
  31. }
  32. return ;
  33. }

atcoder 4142,求满足区间内al+al+1+al+2+...+ar==al^al+1^al+2^...^ar的区间个数

异或性质:a^b<=a+b,当且仅当a&b等于0时取等

  1. #include<stdio.h>
  2. #include<iostream>
  3. using namespace std;
  4. const int maxn=2e5+;
  5. long long a[maxn];
  6. int main()
  7. {
  8. int n,en=,st=;
  9. long long sum=,ans=;
  10. scanf("%d",&n);
  11. for(int i=;i<n;i++)scanf("%lld",&a[i]);
  12. while()
  13. {
  14. while(en<n)
  15. {
  16. if((sum&a[en])==)sum+=a[en++],ans+=en-st;
  17. else break;
  18. }
  19. if(en==n)break;
  20. sum-=a[st++];
  21. }
  22. printf("%lld\n",ans);
  23. return ;
  24. }

洛谷 p1102 a-b数对,这题直接map一下就好了,强行尺取要先来个sort排序,[枚举每个B+查询对应A]复杂度为O(n),sort完二分也可,尺取的优化在于B+C已经比最大的数大了,就break。

(*╹▽╹*)这题没有代码

poj2566,求一段子序列之和的绝对值最接近所给出的t,不能直接用尺取所以前缀+sort一哈,细节略多,试了很久。

  1. #include<stdio.h>
  2. #include<iostream>
  3. #include<algorithm>
  4. #define INF 0x3f3f3f3f
  5. using namespace std;
  6. const int maxn=1e5+;
  7. int n,en,st,k,a[maxn],l,r,sum,ans,res,s;
  8. pair<int,int> pre[maxn];
  9. int main()
  10. {
  11. while(scanf("%d%d",&n,&k)&&n!=&&k!=)
  12. {
  13. pre[]=make_pair(,);
  14. for(int i=;i<=n;i++)scanf("%d",&a[i]),pre[i].first=pre[i-].first+a[i],pre[i].second=i;
  15. sort(pre,pre++n);
  16. while(k--)
  17. {
  18. en=,st=,ans=INF,res=INF; //en=0会wa
  19. scanf("%d",&s);
  20. while(en<=n)
  21. {
  22. int tmp=pre[en].first-pre[st].first;
  23. if(abs(tmp-s)<=res)
  24. {
  25. res=abs(tmp-s);
  26. ans=abs(tmp);
  27. l=pre[st].second,r=pre[en].second;
  28. }
  29. if(tmp<s)en++;
  30. else if(tmp>s)st++;
  31. else break;
  32. if(en==st)en++; //这句没有会wa
  33. }
  34. if(l>r)swap(l,r);
  35. printf("%d %d %d\n",ans,l+,r); //前缀l和r之间包括了数l+1到r,所以刚开始要加pre[0]
  36. }
  37. }
  38. return ;
  39. }

...over

尺取法two pointers的更多相关文章

  1. 51nod 1564 区间的价值 | 分治 尺取法

    51nod 1564 区间的价值 题面 一个区间的价值是区间最大值×区间最小值.给出一个序列\(a\), 求出其中所有长度为k的子区间的最大价值.对于\(k = 1, 2, ..., n\)输出答案. ...

  2. [CodeForces-1225B] TV Subscriptions 【贪心】【尺取法】

    [CodeForces-1225B] TV Subscriptions [贪心][尺取法] 标签: 题解 codeforces题解 尺取法 题目描述 Time limit 2000 ms Memory ...

  3. 5806 NanoApe Loves Sequence Ⅱ(尺取法)

    传送门 NanoApe Loves Sequence Ⅱ Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K ...

  4. POJ3061 尺取法

    题目大意:从给定序列里找出区间和大于等于S的最小区间的长度. 前阵子在zzuli OJ上见过类似的题,还好当时补题了.尺取法O(n) 的复杂度过掉的.尺取法:从头遍历,如果不满足条件,则将尺子尾 部增 ...

  5. POJ 2739 Sum of Consecutive Prime Numbers(尺取法)

    题目链接: 传送门 Sum of Consecutive Prime Numbers Time Limit: 1000MS     Memory Limit: 65536K Description S ...

  6. CF 701C They Are Everywhere(尺取法)

    题目链接: 传送门 They Are Everywhere time limit per test:2 second     memory limit per test:256 megabytes D ...

  7. nyoj133_子序列_离散化_尺取法

    子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:5   描述 给定一个序列,请你求出该序列的一个连续的子序列,使原串中出现的所有元素皆在该子序列中出现过至少1次. 如2 8 ...

  8. Codeforces 676C Vasya and String(尺取法)

    题目大概说给一个由a和b组成的字符串,最多能改变其中的k个字符,问通过改变能得到的最长连续且相同的字符串是多长. 用尺取法,改变成a和改变成b分别做一次:双指针i和j,j不停++,然后如果遇到需要改变 ...

  9. POJ 3061 (二分+前缀和or尺取法)

    题目链接: http://poj.org/problem?id=3061 题目大意:找到最短的序列长度,使得序列元素和大于S. 解题思路: 两种思路. 一种是二分+前缀和.复杂度O(nlogn).有点 ...

随机推荐

  1. maven安装与在eclipse中配置

    需要准备 eclipse maven压缩包 : http://maven.apache.org/download.cgi 1 解压maven压缩包 2 在系统变量中新建变量MAVEN_HOME,值为 ...

  2. K8S入门系列之集群二进制部署-->master篇(二)

    组件版本和配置策略 组件版本 Kubernetes 1.16.2 Docker 19.03-ce Etcd 3.3.17 https://github.com/etcd-io/etcd/release ...

  3. 过滤广告(只能发布 [a-zA-z0-9及汉字,;?.]) ,排除其他特殊符号

      /** * 过滤广告(只能发布 [a-zA-z0-9及汉字,;?.]) ,排除其他特殊符号 * Created by 1 on 2015/8/19. */ public class FilterA ...

  4. Cauchy-Binet公式的证明 及 对Denton et al. (2019)的个人注(1)

    ------------恢复内容开始------------ 据新闻报道数学天才陶哲轩和3个物理学家研究出一个只用特征值就可以计算矩阵特征向量的公式, 我感觉很有趣, 这应该能够应用在很多领域中, 所 ...

  5. ios沙盒机制---基本数据类型的存取和文件的基本操作

    沙盒快速存储及读取 存储:  [[NSUserDefaults standardUserDefaults] setObject:@"abc" forKey:@"1&quo ...

  6. PHP导出成PDF你用哪个插件

    准备工作 首先查询了相关的类库,有FPDF,zendPDF,TcPDF等等.首先看了下先选择了FPDF,可以说除了中文字符以外没有什么问题,中文乱码而且看了下最新版本没有很好的解决方案,所以只能放弃. ...

  7. 星际争霸2 AI开发(持续更新)

    准备 我的环境是python3.6,sc2包0.11.1 机器学习包下载链接:pysc2 地图下载链接maps pysc2是DeepMind开发的星际争霸Ⅱ学习环境. 它是封装星际争霸Ⅱ机器学习API ...

  8. 搭建Nginx正向代理服务

    需求背景: 前段时间公司因为业务需求需要部署一个正向代理,需要内网服务通过正向代理访问到外网移动端厂商域名通道等效果,之前一直用nginx做四层或者七层的反向代理,正向代理还是第一次配置,配置的过程也 ...

  9. 如何在后台封装el-tree所需要的数据格式

    背景 最近遇到了一个分层级展示指标的需求,前端使用el-tree树形组件,要求按官方文档的格式提供数据. 数据格式: id: 1, label: '一级 1', children: id: 4, la ...

  10. Viterbi(维特比)算法在CRF(条件随机场)中是如何起作用的?

    之前我们介绍过BERT+CRF来进行命名实体识别,并对其中的BERT和CRF的概念和作用做了相关的介绍,然对于CRF中的最优的标签序列的计算原理,我们只提到了维特比算法,并没有做进一步的解释,本文将对 ...