模板题——位运算,离散化,区间合并

1.位运算

模板:

#include <bits/stdc++.h>

using namespace std;
const int N = 100010;
//lowbit函数作用:返回x的最后一位1
int lowbit(int x)
{
    return x & (-x);
}

int main(){
 int n;   
 cin >> n;    
 while(n --)
 {
     int a;
     cin>>a;
     int sum = 0;
     while(a)
     {a = a - lowbit(a);
     sum++;}
     printf("%d ",sum);
 }
 return 0;   
}

自己写的

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n;
    cin>>n;
    int a[n+5],b[n+5];
    memset(b,0,sizeof(b));
    for(int i=0;i<n;i++)
    scanf("%d",&a[i]);
    for(int i=0;i<n;i++)
    {
        for(int bit=a[i];bit;bit>>=1)
        {
            if((bit&1)) b[i]++;
        }
    }
    for(int i=0;i<n;i++) printf("%d ",b[i]);
    return 0;
}

n的各位数字是几

//依次输出n的个位数字,即二进制表述形式
int n=10;
for(int k=3;k>=0;k--) cout<<(n>>k)&1<<endl;

2.离散化:值域范围大,数据比较稀疏

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int>PII;
const int N=300010;
int n,m;
int a[N],s[N];//前缀和
vector<int> alls;//待离散化的数组
vector<PII> add,query;//两种操作

int findd(int x)//二分法离散化,找到x在a数组中的下标
{
    int l=0,r=alls.size()-1;
    while(l<r)
    {
        int mid=l+r>>1;
        if(alls[mid]>=x) r=mid;
        else l=mid+1;
    }
    return r+1;
}

int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        int x,c;
        cin>>x>>c;
        add.push_back({x,c});
        alls.push_back(x);//加入待离散化的数组中
    }
    for(int i=0;i<m;i++)
    {
        int l,r;
        cin>>l>>r;
        query.push_back({l,r});
        alls.push_back(l);
        alls.push_back(r);
    }
    //去重
    sort(alls.begin(),alls.end());//先排序
    alls.erase(unique(alls.begin(),alls.end()),alls.end());//删掉重复的元素
    //处理插入操作
    for(auto item : add)
    {
        int x=findd(item.first);
        a[x]+=item.second;//在离散化后的位置加上c,a数组变成前缀和模板
    }
    //处理前缀和
    for(int i=1;i<=alls.size();i++) s[i]=s[i-1]+a[i];
    //处理询问操作
    for(auto item:query)
    {
        int l=findd(item.first),r=findd(item.second);
        cout<<s[r]-s[l-1]<<endl;
    }
    return 0;
}

3.区间合并

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int>PII;
const int N=100010;
int n;
vector<PII> segs;
void mergeg(vector<PII> &segs)
{
    vector<PII> res;
    sort(segs.begin(),segs.end());
    int st=-2e9,ed=-2e9;
    for(auto seg:segs)
    {
        if(ed<seg.first)
        {
            if(st!=-2e9) res.push_back({st,ed});
            st=seg.first,ed=seg.second;
        }
        else ed=max(ed,seg.second);
    }
    if(st!=-2e9) res.push_back({st,ed});
    segs=res;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int l,r;
        cin>>l>>r;
        segs.push_back({l,r});
    }
    mergeg(segs);
    cout<<segs.size()<<endl;
    return 0;
}

校门外的树

#include <bits/stdc++.h>

using namespace std;
const int N=10010;
struct tree
{
    int l,r;
}Seg[N];
bool operator <(const tree&A,const tree&B)
{
    return A.l<B.l;
}
int main()
{
    int m,n;
    cin>>n>>m;
    for(int i=0;i<m;i++) scanf("%d%d",&Seg[i].l,&Seg[i].r);

    sort(Seg,Seg+m);
    int L=Seg[0].l,R=Seg[0].r;
    int sum=0;
    for(int i=1;i<m;i++)
    {
        if(Seg[i].l<=R) R=max(R,Seg[i].r);
        else
        {
            sum+=R-L+1;
            L=Seg[i].l;R=Seg[i].r;
        }
    }
    sum+=R-L+1;
    printf("%d\n",n+1-sum);
    return 0;
}

4.双指针算法

最长连续不重复子序列

#include <bits/stdc++.h>

using namespace std;
const int N=100010;
int a[N],s[N];

int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    int res=0;
    for(int i=0,j=0;i<n;i++)
    {
        s[a[i]]++;
        while(j<=i&&s[a[i]]>1)
        {
            s[a[j]]--;
            j++;
        }
        res=max(res,i-j+1);
    }
    cout<<res<<endl;
    return 0;
}

数组元素的目标和

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,m,x;
    int a[100010],b[100010];
    cin>>n>>m>>x;
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    for(int j=0;j<m;j++) scanf("%d",&b[j]);
    for(int i=0,j=m-1;i<n;i++)
    {
        while(j>=0&&a[i]+b[j]>x)
            j--;
        if(a[i]+b[j]==x)
        {
            printf("%d %d\n",i,j);
            break;
        }
    }
    return 0;
}

3.判断子序列

自己写的

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,m,x;
    int a[100010],b[100010];
    cin>>n>>m;
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    for(int j=0;j<m;j++) scanf("%d",&b[j]);
    int num=0;
    for(int i=0,j=0;j<m;j++)
    {
        if(a[i]==b[j]) {i++;num++;}

    }if(num<n) printf("No\n");
        else printf("Yes\n");
    return 0;
}

模板

#include <bits/stdc++.h>
const int N = 1e5+10;
using namespace std;
int n,m,x;
int a[N],b[N];
int sum;
int main(){
    
    cin>>n>>m;
    for(int i = 0; i < n; i++)
    cin>>a[i];
    for(int j = 0; j < m; j++)
    cin>>b[j];
    int j = 0;
    for(int i = 0; i < m; i++)
    {
        if(j < n && a[j] == b[i]) j++;
        
    }
    if(j == n)
    cout<<"Yes"<<endl;
    else
    cout<<"No"<<endl;
    return 0;
    
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值