参照acwing给出知识点,做的是对应洛谷的模板题,
该帖暂时搁置了,因为博主准备刷一下3月底的csp,去刷板子题去了,4月会回来的!
待问
- 是否可以使用万能头文件
- 上机环境:可不可以使用devc++,学习vscode调试
一、基础算法
- 排序
题目
快排
#include<bits/stdc++.h>
using namespace std;
int n;
void quick_sort(int a[],int l,int r)
{
if(l>=r)return;
int i=l-1,j=r+1,mid=a[(l+r)>>1];
while(i<j)
{
do i++;while(a[i]<mid);
do j--;while(a[j]>mid);
if(i<j)swap(a[i],a[j]);
}
quick_sort(a,l,j);//不能为j-1
quick_sort(a,j+1,r);
}
int main()
{
freopen("in.txt","r",stdin);
int a[100005];
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
quick_sort(a,1,n);
for(int i=1;i<=n;i++)
printf("%d ",a[i]);
return 0;
}
归并排序
#include<bits/stdc++.h>
using namespace std;
int n,a[100005],tmp[100005];
void merge_sort(int l,int r)
{
if (l>=r)return ;
int mid=l+r>>1;
merge_sort(l,mid);
merge_sort(mid+1,r);
int k=l,i=l,j=mid+1;
while(i<=mid&&j<=r)
{
if(a[i]<a[j])tmp[k++]=a[i++];
else tmp[k++]=a[j++];
}
while(i<=mid)tmp[k++]=a[i++];
while(j<=r) tmp[k++]=a[j++];
for(i=l;i<=r;i++)a[i]=tmp[i];
}
int main()
{
freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
merge_sort(1,n);
for(int i=1;i<=n;i++)
printf("%d ",a[i]);
return 0;
}
- 二分
整数二分,跳石头
贪心+二分答案
#include<bits/stdc++.h>
using namespace std;
int len,n,m,a[500005];
bool test(int x)
{
int dis=0,cnt=0,alast=0;
for(int i=1;i<=n;i++)
{
if(a[i]-alast<x)cnt++;//第i块石头需要移走;
else alast=a[i];
if(cnt>m)return 0;
}
return 1;
}
int main()
{
freopen("in.txt","r",stdin);
scanf("%d %d %d",&len,&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
n++;
a[n]=len;
int l=1,r=len,mid;
while(l<=r)
{
mid=l+r>>1;
if(test(mid))l=mid+1;
else r=mid-1;
}
printf("%d",l-1);
return 0;
}
浮点数二分
一元三次方程noip2001的题
法1:求导得
3
a
x
2
+
2
b
x
+
c
=
0
3ax^2+2bx+c=0
3ax2+2bx+c=0,可得两个拐点y1,y2,然后可以直接三分区间
#include<bits/stdc++.h>
using namespace std;
double a,b,c,d;
double f(double x)
{
return a*x*x*x+b*x*x+c*x+d;
}
double get_ans(double l,double r)
{
double mid=(l+r)/2;
while(r-l>1e-3)
{
mid=(l+r)/2;
if(f(l)*f(mid)<0)r=mid;
else l=mid;
}
return mid;
}
int main()
{
freopen("in.txt","r",stdin);
//一定有三个解!!!
scanf("%lf %lf %lf %lf",&a,&b,&c,&d);
double x1,x2,x3,y1,y2,l=-100,r=100;
x1=(-2*b+sqrt(4*b*b-4*3*a*c))/(6*a);
x2=(-2*b-sqrt(4*b*b-4*3*a*c))/(6*a);
y1=min(x1,x2);
y2=max(x1,x2);
x1=get_ans(l,y1);
x2=get_ans(y1,y2);
x3=get_ans(y2,r);
printf("%.2lf %.2lf %.2lf",x1,x2,x3);
return 0;
}
法2枚举:<性能更优>
根据题目条件(根与根之差的绝对值 ≥1)枚举200个区间即可
#include<bits/stdc++.h>
using namespace std;
double a,b,c,d;
void vivi()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
}
void readata()
{
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
}
double f(double x)
{
return a*x*x*x+b*x*x+c*x+d;
}
double finf(double l,double r)
{
double m;
while(r-l>=1e-3)
{
m=(l+r)/2;
if(f(l)*f(m)<0)r=m;
else if(f(l)==0) return l;
else l=m;
}
return l;
}
void work()
{
for(double i=-100;i<=100;i++)
{
double j;
j=i+1;
if(f(i)==0){printf("%.2lf",i);cout<<" ";}
else if(f(i)*f(j)<0){printf("%.2lf",finf(i,j));;cout<<" ";}
}
}
int main()
{
//vivi();
readata();
work();
return 0;
}
- 高精度
- 前缀和与差分
- 双指针算法
- 位运算
- 离散化
- 区间合并
二、数据结构
- 链表与邻接表:树与图的存储
- 栈与队列:单调队列、单调栈.
- kmp
- Trie
- 并查集
关押罪犯
并查集+重载结构体运算符
#include<bits/stdc++.h>
using namespace std;
const int maxn=20005,maxm=100005;
int n,m,fa[maxn<<1];
struct edge{
int x,y,val;
bool operator<(const edge &aa)const{
return val>aa.val;
}
}e[maxm];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main()
{
freopen("in.txt","r",stdin);
int l=0,r=1,mid;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].val);
if(e[i].val>r)r=e[i].val;
}
sort(e+1,e+m+1);
for(int i=1;i<=n+n;i++)fa[i]=i;
for(int i=1;i<=m;i++)
{
int x=e[i].x,y=e[i].y;
if(find(fa[x])==find(fa[y])){
printf("%d ",e[i].val);
return 0;
}
fa[find(x)]=find(y+n);
fa[find(y)]=find(x+n);
}
printf("0");
return 0;
}
- 堆
- Hash表
三、搜索与图论
- DFS与BFS
- 树与图的遍历:拓扑排序·最短路
- 最小生成树
- 二分图:染色法、匈牙利算法
四、 数学知识
- 质数
- 约数
- 欧拉函数
- 快速幂
- 扩展欧几里得算法
- 中国剩余定理
- 高斯消元
- 组合计数
- 容斥原理
- 简单博弈论
五、 动态规划
- 背包问题
- 线性DP
- 区间DP
- 计数类DP
- 数位统计DP
- 状态压缩DP
- 树形DP
- 记忆化搜索
- 贪心