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

时间复杂度: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的更多相关文章

  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. 大宇java面试系列(三):Redis常见面试题

    1. Redis 是什么?都有哪些使用场景? 我们先来理解经典的CAP理论: 一致性:是指从数据层面来看的一致性. 可用性:是指从系统层面的可用性. 容错性:是指从网络层面的的容错性. 数据库逐渐从关 ...

  2. [综合] ISE的综合结果

    1.count2 == 7‘d12,会被综合成下面这个样子, 7‘d12就是左边下面这根绿线,等于符号在中间的圆圈里. 2.什么线都不点的时候,也就什么也没被选中, 而一旦我点击了某根线,却发现图里到 ...

  3. [LC]35题 Search Insert Position (搜索插入位置)

    ①英文题目 Given a sorted array and a target value, return the index if the target is found. If not, retu ...

  4. Java多态——代码示例

    刚开始看多态的文字定义时,总是不明白说的啥意思,看了一些示例代码后,总算知道了,其实也就是“多态”的字面意思. 如下: class A{ public void Out() { System.out. ...

  5. 【Java】面向对象之继承

    多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可.其中如图中所示,食草动物.食肉动物.兔子.羊.狮子.豹都可以称为子类,动物类称为父 ...

  6. 编译spark支持thriftserver

    cdh默认把spark的spark-sql以及hive-thriftserver给弃用掉了,想玩玩thriftserver,于是自己重新编译一个 官网参考: http://spark.apache.o ...

  7. Mac usr/bin 目录 权限问题

    Mac进行 usr/bin 目录下修改权限问题,operation not permitted 一般情况下我们在使用mac系统过程中下载一些文件.新建一些项目之后,这些文件都会默认是只读状态,这时我们 ...

  8. Reverse proxy

    Nginx 反向代理配置: upstream dynamic { zone upstream_dynamic 64k; least_conn; ##适用于long connect,即请求处理时间长 # ...

  9. Matplotlib入门简介

    Matplotlib是一个用Python实现的绘图库.现在很多机器学习,深度学习教学资料中都用它来绘制函数图形.在学习算法过程中,Matplotlib是一个非常趁手的工具. 一般概念 图形(figur ...

  10. 扛把子组2018092609-2 选题 Scrum立会报告+燃尽图 06

    此作业的要求参见[https://edu.cnblogs.com/campus/nenu/2019fall/homework/8681] 一.小组情况组长:迟俊文组员:宋晓丽 梁梦瑶 韩昊 刘信鹏队名 ...