枚举
1.化段为点
前缀和 eg:给一个数列,算x到y个数的和
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> a(n);
vector<int> sum(n+1,0);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum[i+1]=sum[i]+a[i];
}
int x,y;
cin>>x>>y;
cout<<sum[y]-sum[x-1];
}
给一段数字,q次访问,每次对[x,y]区间进行加减x,最后再重新给出新的一段数字
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> a(n+1,0);
vector<int> cha(n+1,0);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
cha[i-1]=a[i]-a[i-1];
}
int q;
cin>>q;
for(int i=0;i<q;i++)
{
int x,y,z;
cin>>x>>y>>z;
cha[x-1]+=z;
cha[y]-=z;
}
for(int i=1;i<=n;i++)
{
a[i]=a[i-1]+cha[i-1];
cout<<a[i]<<endl;
}
}
n棵树,q次砍树区间为[x,y],求之后树总数量
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct sb
{
int pos,num;
};
bool compare(sb x,sb y)
{
if(x.pos == y.pos )
{
return x.num < y.num ;
}
return x.pos < y.pos ;
}
int main()
{
int n,q;
cin>>n>>q;
vector<sb> a(q*2);
for(int i=0;i<q;i++)
{
int x,y;
cin>>x>>y;
if(x>y)
{
int t=x;
x=y;
y=t;
}
a[i].pos=x-1;
a[i].num=1;
a[i+q].pos=y;
a[i+q].num=-1;
}
sort(a.begin() , a.end() ,compare);
int cnt=a[0].pos;
int b=0;
for(int i=0;i<q*2;i++)
{
b=b+a[i].num;
if(b==1&&a[i].num==1&&i>0)
{
cnt+=a[i].pos-a[i-1].pos;
}
}
cnt+=n-a[2*q-1].pos;
cout<<cnt+1;
}
输入n个数,有m区间可以缓存,求需要存多少
#include<iostream>
using namespace std;
int main()
{
int n,m,cnt=0;
cin>>n>>m;
int v[n],a[n];
for(int i=0;i<n;i++)
{
int x;
cin>>x;
if(v[x]==1)
{
continue;
}
a[cnt++]=x;
v[x]=1;
if(cnt>m)
{
v[a[cnt-m-1]]==0;
}
}
cout<<cnt;
}
追逐法/双指针法/尺量法/蚯蚓法:一缩一进
#include<iostream>
#include <algorithm>
using namespace std;
int main()
{
int n,s;
cin>>n>>s;
int a[n];
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
int len=n+1,r=0;
int sum=0;
for(int l=0;l<n;l++)
{
while(r<n&&sum<s)
{
sum+=a[r];
r++;
}
if(sum>=s)
{
len=min(r-l,len);
}
else
{
break;
}
sum-=a[l];
}
if(len>n)
{
printf("0");
}
else
{
printf("%d",len);
}
return 0;
}
计算n个数,i到j最大差值
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int n, maxx = 0;
cin >> n;
vector<int> a(n), minn(n);
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
minn[n - 1] = a[n - 1];
for (int j = n - 2; j >= 0; j--)
{
minn[j] = min(minn[j + 1], a[j]);
}
for (int i = 0; i < n; i++)
{
maxx = max(maxx, a[i] - minn[i]);
}
cout << maxx;
return 0;
}
拼数:将n个数组装成最大数
字符串x+y就是例如233+2331=2332331这样,叠加起来
然后比较就是从头开始一个字符一个比
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
bool comp(string x,string y)
{
return x+y>y+x;
}
int main()
{
int n;
cin>>n;
vector<string> a(n);
for(int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a.begin(),a.end(),comp);
for(int i=0;i<n;i++)
{
cout<<a[i];
}
}
长度为m,数字总和为s的最大值和最小值
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
int main()
{
int m,s;
cin>>m>>s;
if(9*m<s||s<2)
{
return 0;
}
int qian=0;
int zhong=s/9;
if(zhong)
{
qian=s%9;
}
else
{
zhong=s;
}
const string a(qian, '9');
const string b(m-qian-1, '0');
const string c(m-qian-2, '0');
cout<<"最大值:"<<a<<zhong<<b<<endl;
cout<<"最小值:"<<'1'<<c<<zhong-1<<a;
}
国王左手右手金币 比较前后两个a,b来反映全局 "以偏概全"
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct lr
{
int l,r;
};
bool comp(lr x,lr y)
{
return x.l * x.r < y.l * y.r;
}
int main()
{
int n;
cin>>n;
vector<lr> mult(n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&mult[i].l,&mult[i].r);
}
sort(mult.begin(),mult.end(),comp);
long int maxx=0;
long int sum=1;
for(int i=0;i<n;i++)
{
sum=mult[i].l*sum;
maxx=max(maxx,sum/(mult[i].r));//注意类型
}
cout<<maxx;
}
由此处开始递归
我认为递归不要去想太多,直接以偏概全,用片面的想法去循环
归并排序--一分为二
#include <iostream>
using namespace std;
int n;
int a[1000],b[1000];
void hen(int l,int mid,int r)
{
int q=l,p=mid+1;
for(int i=l;i<=r;i++)
{
if(q>mid||(a[p]<=a[q]&&p<=r))
{
b[i]=a[p++];
}
else
{
b[i]=a[q++];
}
}
for(int i=l;i<=r;i++)
{
a[i]=b[i];
}
}
void erfen(int l,int r)
{
if(l==r) return ;
int mid=(l+r)/2;
erfen(l,mid);
erfen(mid+1,r);
hen(l,mid,r);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
erfen(0,n-1);
for(int i=0;i<n;i++)
{
cout<<a[i]<<" ";
}
}
计算逆序对 修改上面代码
void hen(int l, int mid, int r)
{
int q = l, p = mid + 1;
for (int i = l; i <= r; i++)
{
if (q > mid || (a[p] <= a[q] && p <= r))
{
b[i] = a[p++];
cnt += (mid - q + 1); // 更新逆序对的数量
}
else
{
b[i] = a[q++];
}
}
for (int i = l; i <= r; i++)
{
a[i] = b[i];
}
}
汉诺塔新解:这次就是按照上面我所说的直接列出来
#include<iostream>
using namespace std;
int cnt=0;
void han(int n,char qi,char mo,char zhong)
{
if(n==0) return ;
han(n-1,qi,zhong,mo);//
cout<<qi<<"->"<<mo<<endl;
cnt++;
han(n-1,zhong,mo,qi);
}
int main()
{
int n;scanf("%d",&n);
han(n,'x','z','y');
cout<<cnt;
}
递归计算器
#include <iostream>
#include <cstdlib> // 包含 std::atof 函数的头文件
#include <cmath>
using namespace std;
string a;
double zhuan(int l, int r)
{
string num_str(a.begin() + l, a.begin() + r);
return std::atof(num_str.c_str());
}
double suan(int l,int r)
{
int cnt=0;
int pos1=-1,pos2=-1,pos3=-1;
for(int i=l;i<r;i++)
{
if(a[i]=='(') cnt++;
if(a[i]==')') cnt--;
if(cnt==0)
{
if(a[i]=='+'||a[i]=='-') pos1=i;
else if(a[i]=='*'||a[i]=='/') pos2=i;
else if(a[i]=='^') pos3=i;
}
}
if(pos1==-1&&pos2==-1&&pos3==-1)
{
if(cnt==0&&a[l]=='(') return suan(l+1,r-1);
else if(cnt<0&&a[r]==')') return suan(l,r-1);
else if(cnt>0&&a[l]=='(') return suan(l+1,r);
return zhuan(l,r);
}
if(pos1!=-1)
{
if(a[pos1]=='+') return suan(l,pos1) + suan(pos1+1,r);
else return suan(l,pos1) - suan(pos1+1,r);
}
else if(pos2!=-1)
{
if(a[pos2]=='*') return suan(l,pos2) * suan(pos2+1,r);
else return suan(l,pos2) / suan(pos2+1,r);
}
else if(pos3!=-1)
{
return pow(suan(l,pos3),suan(pos3+1,r));
}
}
int main()
{
cin>>a;
int len=a.size();
cout<<suan(0,len);
}
上面代码前部分的字符串转换数字也可以这样
double zhuan(int l,int r)
{
double num=0;
int i=l;
for(;i<r;i++)
{
if(a[i]!='.')
{
num = num*10 + a[i] - '0';
}
else
{
i++;
break;
}
}
double d=0.1;
for(;i<r;i++)
{
num = num + (a[i] - '0')*d;
d*=0.1;
}
return num;
}
n行四列数,随机总和为0
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 4000;
int n, a[4][N];
void pre(vector<int>& p, int x, int y)
{
int cnt = 0;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
p[++cnt] = a[x][i] + a[y][j];
}
}
}
int main()
{
cin >> n;
for(int i=0; i<n; i++)
{
cin >> a[0][i] >> a[1][i] >> a[2][i] >> a[3][i];
}
n *= n;
vector<int> q(n), p(n);
pre(p, 0, 1);
pre(q, 2, 3);
sort(q.begin(), q.end());
int cnt = 0;
for(int i=0; i<n; i++)
{
cnt += upper_bound(q.begin(), q.end(), -p[i]) - lower_bound(q.begin(), q.end(), -p[i]);
}
cout << cnt << endl;
return 0;
}
lower_bound(q.begin(), q.end(), -p[i])
:在有序序列 q 中查找第一个大于或等于 -p[i] 的元素,返回该元素的迭代器。upper_bound(q.begin(), q.end(), -p[i])
:在有序序列 q 中查找第一个大于 -p[i] 的元素,返回该元素的迭代器。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int arr[] = {1, 2, 2, 3, 3, 3, 4, 5, 6, 6};
vector<int> vec(arr, arr + sizeof(arr) / sizeof(arr[0]));
vector<int>::iterator lower = lower_bound(vec.begin(), vec.end(), 3);
vector<int>::iterator upper = upper_bound(vec.begin(), vec.end(), 3);
cout << "Lower bound index: " << lower - vec.begin() << endl; // 输出 3,即第一个 3 的位置
cout << "Upper bound index: " << upper - vec.begin() << endl; // 输出 6,即最后一个 3 的下一个位置
cout << "Number of 3s: " << upper - lower << endl; // 输出 3,即元素 3 的个数
return 0;
}
二分法:空教室分配
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct jiao
{
int a,b,d;
};
int n,m;
vector<jiao> s(1000);
int r[1000],delat[1000];
bool judge(int x)
{
for(int i=0;i<n;i++)
{
if(i==0)
{
delat[i]=r[i];
}
else
{
delat[i]=r[i]-r[i-1];
}
}
for(int i=0;i<x;i++)
{
delat[s[i].a+1]-=s[i].d;
delat[s[i].b+1]+=s[i].d;
}
int sum=0;
for(int i=0;i<n;i++)
{
sum+=delat[i];
if(sum<0) return 0;
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
scanf("%d",&r[i]);
}
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&s[i].d,&s[i].a,&s[i].b);
}
int l=0,r=m;
while(l<r)
{
int mid=(l+r)/2;
if(judge(mid)) l=mid+1;
else r=mid;
}
if(l==m) cout<<0;
else cout<<"-1\n"<<l;
}
烘干机
#include <iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int n, k;
int a[1000];
bool judge(int x)
{
int cnt = 0,t=upper_bound(a,a+n,x) - a;
for (int i = t; i < n; i++)
{
cnt += ceil((a[i] - x)/double(k - 1));//这里的k-1是为了节省完整一件衣服的时间
}
return cnt <= x;
}
int main()
{
cin >> n >> k;
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
sort(a,a+n);
int l = 1, r = 2e9;
while (l < r)
{
int mid = l+r >> 1;
if (judge(mid))
r = mid;
else
l = mid + 1;
}
cout << l;
}