本篇文章只给出代码模板,以及自己对该模板的理解。如果想看正确的算法思路,可以移步AcWing官网看详情。链接:常用代码模板1——基础算法 - AcWing
如有理解错误,欢迎大家批评指正。
void quick_sort(int q[],int l,int r){//q是传入的数组,[l,r]是需要排序的范围
if(l>=r) return;
int i = l-1,j = r+1,x = q[l+r>>1];
while(ix);
if(i
int tmp[N];//需要开一个临时数组tmp[],N至少跟传入的q[]数组的范围一致
void merge_sort(int q[],int l,int r){
if(l>=r) return;
int mid = r+l>>1;
merge_sort(q,l,mid),merge_sort(q,mid+1,r);
int k = 0,i = l,j = mid+1;
while(i<=mid&&j<=r){
if(q[i]<=q[j]) tmp[k++]=q[i++];
else tmp[k++]=q[j++];
}
while(i<=mid) tmp[k++]=q[i++];
while(j<=r) tmp[k++]=q[j++];
for(int i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];
}
bool check(int x){//check函数检查x是否满足某种性质
//根据题意完善check()函数
}
//区间被划分为[l,mid],[mid+1,r]
int bsearch1(int l,int r){
while(l>1;
if(check(mid)) r=mid;
else l=mid+1;
}
return l;
}
bool check(int x){//check函数检查x是否满足某种性质
//根据题意完善check()函数
}
//区间被划分为[l,mid-1],[mid,r]
int bsearch2(int l,int r){
while(l>1;
if(check(mid)) l=mid;
else r=mid+1;
}
return l;
}
bool check(double x){//check函数检查x是否满足某种性质
//根据题意完善check()函数
}
double bsearch3(double l,double r){
const double eps = 1e-8;//定义精度:如果题目要求精确到小数点后六位小数,eps最好开到1e-8保险
while(r-l>eps){
double mid = (l+r)/2;
if(check(mid)) r = mid;
else l = mid;
}
return l;
}
string a;cin >> a;//以字符串读入大整数
vector A;//使用vector A从个位往高位存储即逆序存储
for(int i = a.size()-1;i>=0;i--) A.push_back(s[i]-'0');
//C=A+B,A>=0,B>=0
//C++中&还可用于引用变量,常用于传参和定义别名
//如第6行代码,若写成
//vector add(vector B){
//可能会爆内存并且会严重拖慢程序运行速度
vector add(vector &A,vector &B){//参数为大整数A,B,返回A+B的vector
if(A.size() C;
int t = 0;//t表示进位
for(int i = 0;i
//C=A-B,A>=0,B>=0
vector sub(vector &A,vector &B){//参数为大整数A,B,返回A-B的vector
vector C;
int t = 0;//t表示借位
for(int i = 0;i1&&C.back()==0) C.pop_back();//去除前导零
return C;
}
//C=A*b,A>=0,b>=0
vector mul(vector &A,int b){//参数为大整数A,小整数b,返回A*b的vector
vector C;
int t = 0;//t表示进位值(区别于A+B的进位,t可能是很大的)
for(int i = 0;i1&&C.back()==0) C.pop_back();//去除前导零
return C;
}
//A/b==C...r,A>=0,b>=0
vector div(vector &A,int b,int &r){//参数为大整数A,小整数b,r用于带回计算出的余数
vector C;
r = 0;
for(int i = A.size();i>=0;i--){
r=r*10+A[i];
C.push_back(r/b);
r%=b;
}
reverse(C.begin(),C.end());//反转C,方便去除前导零和输出
while(C.size()>1&&C.back()==0) C.pop_back();//去除前导零
return C;
}
//如果我们要求数组a[]大量的子区间[l,r]的数之和
const int N = 1e6+5;
int a[N],prefix[N];//preifx[]为前缀和数组
void solve(){
int n;cin >> n;//有n个数,1<=n<=1000000
for(int i = 1;i<=n;i++) cin >> a[i];//下标一定从1开始
//计算前缀和
for(int i = 1;i<=n;i++) prefix[i]=prefix[i-1]+a[i];
int q;cin >> q;//有q次询问
while(q--){
int l,r;cin >> l >> r;//[l,r]为询问区间
//输出子区间[l,r]的数之和
cout << prefix[r]-prefix[l-1] << endl;//endl -> '\n'
}
}
//如果我们要求矩阵a[][]大量的子矩阵(a[x1][y1]和a[x2][y2]组成的子矩阵)的数之和
const int N = 1e3+5;
int a[N][N],prefix[N][N];//prefix[][]为前缀和数组
void solve(){
int n;cin >> n;//n行n列的矩阵,1<=n<=1000
for(int i = 1;i<=n;i++) for(int j = 1;j<=n;j++) cin >> a[i][j];//下标从1开始
//计算前缀和
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
prefix[i][j]=prefix[i-1][j]+prefix[i][j-1]+a[i][j]-preifx[i-1][j-1];
}
}
int q;cin >> q;//q次询问
while(q--){
int x1,y1,x2,y2;cin >> x1 >> y1 >> x2 >> y2;//子矩阵的范围
//输出子矩阵数之和
cout << prefix[x2][y2]-preifx[x1-1][y2]-prefix[x2][y1-1]+prefix[x1-1][y1-1] << endl;//endl -> '\n'
}
}
//如果我们要大量统一修改数组a[]的区间[l,r]的值,使该区间的数都加上x,并要我们输出最终修改后的数组
const int N = 1e6+5;
int a[N],diff[N];//diff[]为差分数组
void solve(){
int n;cin >> n;//有n个数,1<=n<=1000000
for(int i = 1;i<=n;i++) cin >> a[i];//下标从1开始
//计算差分数组
for(int i = 1;i<=n;i++) diff[i]=a[i]-a[i-1];
int q;cin >> q;//q次修改
while(q--){
int l,r,x;cin >> l >> r >> x;//[l,r]区间内的数都加x
diff[l]+=x,diff[r+1]-=x;
}
for(int i = 1;i<=n;i++) a[i]=a[i-1]+diff[i];//构造修改后的数组a[]
for(int i = 1;i<=n;i++) cout << a[i] << " \n"[i==n];//遍历输出,输出完最后一个数后输出换行
}
//如果我们要大量统一修改矩阵a[][]的子矩阵(a[x1][y1]和a[x2][y2]形成的子矩阵),使该区间都加上x,并要我们输出最终修改后的数组
const int N = 1e3+5;
int a[N][N],diff[N][N];//diff[][]为差分数组
void update(int x1,int y1,int x2,int y2,int x){
diff[x1][y1]+=x,diff[x2+1][y2+1]+=x,diff[x1][y2+1]-=x,diff[x2+1][y1]-=x;
}
void solve(){
int n;cin >> n;//n行n列的矩阵,1<=n<=1000
for(int i = 1;i<=n;i++) for(int j = 1;j<=n;j++) cin >> a[i][j];//下标从1开始
//计算差分数组
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
update(i,j,i,j,a[i][j]);//计算其实就是每次修改一个1×1的小矩阵
}
}
int q;cin >> q;//q次询问
while(q--){
int x1,y1,x2,y2;cin >> x1 >> y1 >> x2 >> y2;//子矩阵的范围
//实现修改
update(x1,y1,x2,y2,x);
}
//构造回最终修改后的矩阵a[][]
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]-diff[i][j];
}
}
//遍历输出,输出完一行后换行
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++) cout << a[i][j] << " \n"[j==n];
}
}
bool check(int i,int j){
//具体问题的逻辑
}
void solve(){
for(int i = 0,j=0;i
求整数n的第k位二进制数字
int find(int n){
return n>>k&1;
}
void solve(){
int n;cin >> n;//读入n
cout << find(n) << endl;//调用函数并输出结果
}
求整数n的二进制表示中最低位的1的值
int lowbit(int n){//这个计算就被称为lowbit操作
return n&(-n);
}
//如:求6的lowbit,6表示二进制补码为(0……0110)即29个'0'+"110"
//-6的补码为(1……1010)即29个'1'+"010"
//而(0……0110)&(1……1010) --> (0……0010)即结果的二进制为30个'0'+"10",转换为十进制的值为2
void solve(){
int n;cin >> n;//读入n
cout << lowbit(n) << endl;//调用函数并输出结果
}
vector alls;//存储所有待离散化的值
//使用vector排序去重(要求会默写)
sort(alls.begin(),alls.end());
alls.erase(unique(alls.begin(),alls.end()),alls.end());
// 二分求出x对应的离散化的值
int find(int x){//找到第一个大于等于x的位置
int l=0,r=alls.size()-1;
while (l>1;
if(alls[mid]>=x) r=mid;
else l=mid+1;
}
return r+1;//映射到1,2,...,n
}
// 将所有存在交集的区间合并
void merge(vector &segs){//PII->pair,pair存储的是左端点l和右端点r的二元组,合并后的结果放回segs
vector res;
sort(segs.begin(),segs.end());
int st=-2e9,ed=-2e9;
for(auto seg:segs){
if(ed