双指针和位运算

一、博客园

双指针技巧汇总 - murphy_gb - 博客园

二、模板

for (int i = 0, j = 0; i < n; i ++ )
{
    while (j < i && check(i, j)) j ++ ;

    // 具体问题的逻辑
}
常见问题分类:
    (1) 对于一个序列,用两个指针维护一段区间
    (2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作

三、Acwing  799

/*
for (int i = 0, j = 0; i < n; i ++ )
{
    while (j < i && check(i, j)) j ++ ;

    // 具体问题的逻辑
}
常见问题分类:
    (1) 对于一个序列,用两个指针维护一段区间
    (2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作
    
双指针算法核心:优化
两根指针本来暴力求解是n^2级别,双指针运用某些单调性质优化后,时间复杂度变为n,
因为总体看来两根指针都是遍历序列一次
*/
#include<iostream>
using namespace std;
const int N=100010;
int n;
int a[N],b[N];
//a[N]存储整数序列,b[N]动态存储当前探索区间每个元素出现的次数
//注意a的数组范围是元素有多少个,b的数组范围是数组a中元素的取值范围

int main(){
    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];
    
    int res=0;
    for(int i=0,j=0;i<n;i++){//所求子序列可能以任意元素结尾,遍历每个元素
        b[a[i]]++;//元素一个一个去加,如果有重复,一定是新加的元素重复
        while(j<i&&b[a[i]]>1) b[a[j++]]--;
        res=max(res,i-j+1);
    }
    cout<<res<<endl;
    return 0;
}

AcWing 800. 数组元素的目标和

#include<iostream>
using namespace std;
const int N=100010;
int n,m,x;
int A[N],B[N];

int main(){
    cin>>n>>m>>x;
    for(int i=0;i<n;i++) cin>>A[i];
    for(int i=0;i<m;i++) cin>>B[i];
    
    for(int i=0,j=m-1;i<n;i++){
        while(j>=0&&A[i]+B[j]>x) j--;
        if(j>=0&&A[i]+B[j]==x) cout<<i<<' '<<j<<endl;
    }
    return 0;
}

AcWing 2816. 判断子序列

/*
序列a中每个元素能否顺次映射到b
从前往后扫描数组b,每次扫描时,查看数组b中当前数与数组a中当前数是否一样
如果一样,此时a[i]与b[j]匹配,i++
总之就是在数组b中一个一个找与a[i]相匹配的元素,匹配成功就i++
*/
#include <iostream>

using namespace std;

const int N = 100010;

int n, m;
int a[N], b[N];

int main()
{
    cin>>n>>m;
    for (int i = 0; i < n; i ++ ) cin>>a[i];
    for (int i = 0; i < m; i ++ ) cin>>b[i];

    int i = 0, j = 0;
    while (i < n && j < m)
    {
        if (a[i] == b[j]) i ++ ;
        j ++ ;
    }

    if (i == n) puts("Yes");
    else puts("No");

    return 0;
}

四、位运算

n>>k&1   求n的第k位数字

lowbit(n)=n&-n   的作用是求最后的1.

思路:

 AcWing 801. 二进制中1的个数

输入第一个数代表:接下来输入的个数

输入的数转换二进制后,求出1的个数

/*
数字n的二进制表示中倒数第k位数是多少(k从0开始)
n>>k&1
先把第k位移到最后一位n>>k
再看个位是多少:&1


返回x最后一个1 
lowbit(x)=x&-x
补码-x是对x取反+1
反码是对x取反
x=10100   lowbit(x)=100 树状数组的基本操作
*/
#include<iostream>
using namespace std;

int main(){
    int n;
    cin>>n;
    while(n--){
        int x;
        cin>>x;
        int res=0;
        while(x){
            x-=x&(-x);//每次把x中最后一个1减掉
            res++;
        }
        cout<<res<<' ';
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值