分治 1
“Divide And Conquer”
把一个问题划分成几个相似子问题先求解
然后把这个子问题的解合并在一起
(一般还要依据子问题的解再做一遍求解)
这就是典型的分治思想——“分,治,合”
于是接下来就是最普通的分治:
归并排序&逆序对
分:递归左右子区间
治:(就是你在递归调用函数的时候相当于做了排序)
合:对于左右区间排好序的部分再进行一次合并
递归左右两边深度不超过
Code:
点击查看代码
//远古码了应该是,这是个归并排序求逆序对的板子
//但是我不会修了
const int x=3000000+10;
int n;
int a[x],r[x];
long long ans;
void mergesort(int s,int t){
int m,i,j,k;
if(s==t){
return;
}
m=(s+t)/2;
mergesort(s,m);
mergesort(m+1,t);
i=s;
j=m+1;
k=s;
while(i<=m&&j<=t){
if(a[i]<=a[j]){
r[k]=a[i];
i++;
k++;
}
else{
r[k]=a[j];
j++;
k++;
ans+=(m-i+1);
}
}
while(i<=m){
r[k]=a[i];
i++;
k++;
}
while(j<=t){
r[k]=a[j];
j++;
k++;
}
for(int i=s;i<=t;i++){
a[i]=r[i];
}
}
快速幂
咱也不知道为啥就是分治
就是基于这么两个事情:
很显然,因为原式在不取模状态下还是成立的
然后我们就看指数的情况,进行二进制划分
令
然后对于我们的结果来说直接就乘上
Code
点击查看代码
//同样是远古码但是懒得修了
//虽然再写一版可能用不了多长时间
//Lucas板子差不多不超过5min吧
int work(int a,int b,int c){
int ans=1;
a=a%c;
while(b>0){
if(b&1){
ans=(ans*a)%c;
}
b=b>>1;
a=(a*a)%c;
}
return ans;
}
一般倍增就是和二进制划分结合起来的,时间复杂度会
二分答案
二分答案是在函数保证有单调性的时候使用的
就是先猜一个答案,判定合法与否,合法就向更优方向靠近
首先在定义域上找两个点,取中值
然后把中值代入判定是否合法
如果合法向更优方向,不合法向合法方向更改区间范围
重复上述过程直到区间足够确定答案
框架:
点击查看代码
bool check(int mid){
/*验证答案是否合法*/
}
int main(){
/*其他东西*/
int l=0,r=inf,ans;//左右端点和答案
while(l<r){
int mid=(l+r)/2;
if(check(mid)){
/*向更优方向移动*/
ans=mid;
}
else{
/*向合法方向移动*/
}
}
ans=l;
/*别的东西*/
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具