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;
}