尺取法two pointers
目的:对给定的一个序列,在序列中寻找包含全部需求的、长度最小的一段子序列。一般用来解决具有单调性的区间问题。
时间复杂度:O(n)
https://blog.csdn.net/lxt_lucia/article/details/81091597
自用模板:
poj3061,给定一个序列,使得其和大于或等于S,求最短的子序列长度。
- #include<stdio.h>
- #include<iostream>
- #define INF 0x3f3f3f3f
- using namespace std;
- const int maxn=1e5+;
- int main()
- {
- int T;
- scanf("%d",&T);
- while(T--)
- {
- int n,s,a[maxn],st=,en=,ans=INF;
- long long sum=;
- scanf("%d%d",&n,&s);
- for(int i=;i<n;i++)scanf("%d",&a[i]);
- while()
- {
- while(en<n&&sum<s)sum+=a[en++];
- if(sum<s)break; //如果右端点移动到区间末尾其和还不大于等于S,结束区间的枚举
- ans=min(ans,en-st);
- sum-=a[st++];
- }
- if(ans==INF)ans=;
- printf("%d\n",ans);
- }
- return ;
- }
poj3320,一本书有P页,每一页都一个知识点,求去最少的连续页数覆盖所有的知识点,使用map来查询次数。
- #include<stdio.h>
- #include<iostream>
- #include<map>
- #include<set>
- #define INF 0x3f3f3f3f
- using namespace std;
- const int maxn=1e6+;
- map<int,int> mp;
- set<int> s;
- int main()
- {
- int n,a[maxn],st=,en=,ans=INF,num,sum=;
- scanf("%d",&n);
- for(int i=;i<n;i++)scanf("%d",&a[i]),s.insert(a[i]);
- num=s.size();
- while()
- {
- while(en<n&&sum<num)
- {
- if(mp[a[en]]==)sum++;
- mp[a[en]]++;
- en++;
- }
- if(sum<num)break;
- ans=min(ans,en-st);
- mp[a[st]]--;
- if(mp[a[st]]==)sum--;
- st++;
- }
- if(ans==INF)ans=;
- printf("%d\n",ans);
- return ;
- }
poj2739,找到某一个区间使得连续和等于某一给定值k。
- #include<stdio.h>
- #include<iostream>
- #define INF 0x3f3f3f3f
- using namespace std;
- const int maxn=1e5+;
- bool prime[maxn];
- int p[maxn],tot;
- void init()
- {
- for(int i=;i<;i++)prime[i]=true;
- for(int i=;i<;i++)
- {
- if(prime[i])p[tot++]=i;
- for(int j=;j<tot&&i*p[j]<;j++)
- {
- prime[i*p[j]]=false;
- if(i%p[j]==)break;
- }
- }
- }
- int main()
- {
- init();
- int n;
- while(scanf("%d",&n),n!=)
- {
- int st=,en=,ans=,sum=;
- while()
- {
- while(en<n&&sum<n)sum+=p[en++];
- if(sum==n)ans++;
- if(st==en)break;
- sum-=p[st++];
- }
- printf("%d\n",ans);
- }
- return ;
- }
poj2100,找到某一个区间使得区间内的数的平方和等于某一给定值k。不加1LL的比较超时了(什么鬼哦),代码二的样式我jio的不错。
- #include<stdio.h>
- #include<iostream>
- #define INF 0x3f3f3f3f
- using namespace std;
- const int maxn=1e5+;
- struct node
- {
- int l,r;
- }p[maxn];
- int main()
- {
- long long n;
- scanf("%lld",&n);
- int st=,en=,ans=,k=;
- long long sum=;
- while()
- {
- while(1ll*en*en<=n&&sum<n)sum+=1ll*en*en,en++;
- if(sum==n)ans++,p[k].l=st,p[k++].r=en-;
- if(sum<n)break;
- sum-=1ll*st*st,st++;
- }
- printf("%d\n",ans);
- for(int i=;i<k;i++)
- {
- printf("%d ",p[i].r-p[i].l+);
- for(int j=p[i].l;j<p[i].r;j++)
- printf("%d ",j);
- printf("%d\n",p[i].r);
- }
- return ;
- }
- #include<stdio.h>
- #include<iostream>
- #define INF 0x3f3f3f3f
- using namespace std;
- const int maxn=1e5+;
- struct node
- {
- int l,r;
- }p[maxn];
- int main()
- {
- long long n,sum=,st=,en=;
- int ans=,k=;
- scanf("%lld",&n);
- while()
- {
- if(sum==n)ans++,p[k].l=st,p[k++].r=en-;
- if(sum>=n)sum-=1ll*st*st,st++;
- else
- {
- if(en*en<=n)sum+=1ll*en*en,en++;
- else break;
- }
- }
- printf("%d\n",ans);
- for(int i=;i<k;i++)
- {
- printf("%lld ",p[i].r-p[i].l+);
- for(long long j=p[i].l;j<p[i].r;j++)
- printf("%lld ",j);
- printf("%lld\n",p[i].r);
- }
- return ;
- }
uva 11572,求没有重复数字的最长区间。
- #include<bits/stdc++.h>
- using namespace std;
- #define INF 0x3f3f3f3f
- const int maxn=1e6+;
- int a[maxn];
- int main()
- {
- int T;
- scanf("%d",&T);
- while(T--)
- {
- map<int,int> mp;
- int n,ans=,st=,en=,sum=;
- scanf("%d",&n);
- for(int i=;i<n;i++)scanf("%d",&a[i]);
- while()
- {
- while(en<n)
- {
- if(mp[a[en]]==)sum++,mp[a[en]]++,en++;
- else break;
- }
- ans=max(ans,en-st);
- if(en==n)break;
- if(mp[a[st]]==)mp[a[st]]--;
- sum--;
- st++;
- }
- printf("%d\n",ans);
- }
- return ;
- }
atcoder 4142,求满足区间内al+al+1+al+2+...+ar==al^al+1^al+2^...^ar的区间个数
异或性质:a^b<=a+b,当且仅当a&b等于0时取等
- #include<stdio.h>
- #include<iostream>
- using namespace std;
- const int maxn=2e5+;
- long long a[maxn];
- int main()
- {
- int n,en=,st=;
- long long sum=,ans=;
- scanf("%d",&n);
- for(int i=;i<n;i++)scanf("%lld",&a[i]);
- while()
- {
- while(en<n)
- {
- if((sum&a[en])==)sum+=a[en++],ans+=en-st;
- else break;
- }
- if(en==n)break;
- sum-=a[st++];
- }
- printf("%lld\n",ans);
- return ;
- }
洛谷 p1102 a-b数对,这题直接map一下就好了,强行尺取要先来个sort排序,[枚举每个B+查询对应A]复杂度为O(n),sort完二分也可,尺取的优化在于B+C已经比最大的数大了,就break。
(*╹▽╹*)这题没有代码
poj2566,求一段子序列之和的绝对值最接近所给出的t,不能直接用尺取所以前缀+sort一哈,细节略多,试了很久。
- #include<stdio.h>
- #include<iostream>
- #include<algorithm>
- #define INF 0x3f3f3f3f
- using namespace std;
- const int maxn=1e5+;
- int n,en,st,k,a[maxn],l,r,sum,ans,res,s;
- pair<int,int> pre[maxn];
- int main()
- {
- while(scanf("%d%d",&n,&k)&&n!=&&k!=)
- {
- pre[]=make_pair(,);
- for(int i=;i<=n;i++)scanf("%d",&a[i]),pre[i].first=pre[i-].first+a[i],pre[i].second=i;
- sort(pre,pre++n);
- while(k--)
- {
- en=,st=,ans=INF,res=INF; //en=0会wa
- scanf("%d",&s);
- while(en<=n)
- {
- int tmp=pre[en].first-pre[st].first;
- if(abs(tmp-s)<=res)
- {
- res=abs(tmp-s);
- ans=abs(tmp);
- l=pre[st].second,r=pre[en].second;
- }
- if(tmp<s)en++;
- else if(tmp>s)st++;
- else break;
- if(en==st)en++; //这句没有会wa
- }
- if(l>r)swap(l,r);
- printf("%d %d %d\n",ans,l+,r); //前缀l和r之间包括了数l+1到r,所以刚开始要加pre[0]
- }
- }
- return ;
- }
...over
尺取法two pointers的更多相关文章
- 51nod 1564 区间的价值 | 分治 尺取法
51nod 1564 区间的价值 题面 一个区间的价值是区间最大值×区间最小值.给出一个序列\(a\), 求出其中所有长度为k的子区间的最大价值.对于\(k = 1, 2, ..., n\)输出答案. ...
- [CodeForces-1225B] TV Subscriptions 【贪心】【尺取法】
[CodeForces-1225B] TV Subscriptions [贪心][尺取法] 标签: 题解 codeforces题解 尺取法 题目描述 Time limit 2000 ms Memory ...
- 5806 NanoApe Loves Sequence Ⅱ(尺取法)
传送门 NanoApe Loves Sequence Ⅱ Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/131072 K ...
- POJ3061 尺取法
题目大意:从给定序列里找出区间和大于等于S的最小区间的长度. 前阵子在zzuli OJ上见过类似的题,还好当时补题了.尺取法O(n) 的复杂度过掉的.尺取法:从头遍历,如果不满足条件,则将尺子尾 部增 ...
- POJ 2739 Sum of Consecutive Prime Numbers(尺取法)
题目链接: 传送门 Sum of Consecutive Prime Numbers Time Limit: 1000MS Memory Limit: 65536K Description S ...
- CF 701C They Are Everywhere(尺取法)
题目链接: 传送门 They Are Everywhere time limit per test:2 second memory limit per test:256 megabytes D ...
- nyoj133_子序列_离散化_尺取法
子序列 时间限制:3000 ms | 内存限制:65535 KB 难度:5 描述 给定一个序列,请你求出该序列的一个连续的子序列,使原串中出现的所有元素皆在该子序列中出现过至少1次. 如2 8 ...
- Codeforces 676C Vasya and String(尺取法)
题目大概说给一个由a和b组成的字符串,最多能改变其中的k个字符,问通过改变能得到的最长连续且相同的字符串是多长. 用尺取法,改变成a和改变成b分别做一次:双指针i和j,j不停++,然后如果遇到需要改变 ...
- POJ 3061 (二分+前缀和or尺取法)
题目链接: http://poj.org/problem?id=3061 题目大意:找到最短的序列长度,使得序列元素和大于S. 解题思路: 两种思路. 一种是二分+前缀和.复杂度O(nlogn).有点 ...
随机推荐
- maven安装与在eclipse中配置
需要准备 eclipse maven压缩包 : http://maven.apache.org/download.cgi 1 解压maven压缩包 2 在系统变量中新建变量MAVEN_HOME,值为 ...
- K8S入门系列之集群二进制部署-->master篇(二)
组件版本和配置策略 组件版本 Kubernetes 1.16.2 Docker 19.03-ce Etcd 3.3.17 https://github.com/etcd-io/etcd/release ...
- 过滤广告(只能发布 [a-zA-z0-9及汉字,;?.]) ,排除其他特殊符号
/** * 过滤广告(只能发布 [a-zA-z0-9及汉字,;?.]) ,排除其他特殊符号 * Created by 1 on 2015/8/19. */ public class FilterA ...
- Cauchy-Binet公式的证明 及 对Denton et al. (2019)的个人注(1)
------------恢复内容开始------------ 据新闻报道数学天才陶哲轩和3个物理学家研究出一个只用特征值就可以计算矩阵特征向量的公式, 我感觉很有趣, 这应该能够应用在很多领域中, 所 ...
- ios沙盒机制---基本数据类型的存取和文件的基本操作
沙盒快速存储及读取 存储: [[NSUserDefaults standardUserDefaults] setObject:@"abc" forKey:@"1&quo ...
- PHP导出成PDF你用哪个插件
准备工作 首先查询了相关的类库,有FPDF,zendPDF,TcPDF等等.首先看了下先选择了FPDF,可以说除了中文字符以外没有什么问题,中文乱码而且看了下最新版本没有很好的解决方案,所以只能放弃. ...
- 星际争霸2 AI开发(持续更新)
准备 我的环境是python3.6,sc2包0.11.1 机器学习包下载链接:pysc2 地图下载链接maps pysc2是DeepMind开发的星际争霸Ⅱ学习环境. 它是封装星际争霸Ⅱ机器学习API ...
- 搭建Nginx正向代理服务
需求背景: 前段时间公司因为业务需求需要部署一个正向代理,需要内网服务通过正向代理访问到外网移动端厂商域名通道等效果,之前一直用nginx做四层或者七层的反向代理,正向代理还是第一次配置,配置的过程也 ...
- 如何在后台封装el-tree所需要的数据格式
背景 最近遇到了一个分层级展示指标的需求,前端使用el-tree树形组件,要求按官方文档的格式提供数据. 数据格式: id: 1, label: '一级 1', children: id: 4, la ...
- Viterbi(维特比)算法在CRF(条件随机场)中是如何起作用的?
之前我们介绍过BERT+CRF来进行命名实体识别,并对其中的BERT和CRF的概念和作用做了相关的介绍,然对于CRF中的最优的标签序列的计算原理,我们只提到了维特比算法,并没有做进一步的解释,本文将对 ...