分治初步

分治初步

归并排序求逆序对

Sol:在归并排序过程中,本身就是分治思想,递归的对左区间排序,右区间同理。对于已经有序两段进行合并只需要O(n)的时间,递归共log2n层,时间复杂度为O(nlog2n)

debug:1.对于没有到达边界的一段也需要放入临时数组,并且继续统计答案

2,先审核一遍代码,出现了没有调用函数,只打个括号的情况,没有报错,需要注意

int solve(int l,int r){ if(l==r)return 0; int mid=(l+r)>>1; int res=solve(l,mid)+solve(mid+1,r); int pl=l,pr=mid+1; int cnt=0; while(pl<=mid&&pr<=r){ if(a[pl]<=a[pr]){ c[++cnt]=a[pl++]; res+=pr-1-(mid+1)+1; } else { c[++cnt]=a[pr++]; } } //还需要处理没到边界的一侧 while(pl<=mid){c[++cnt]=a[pl++];res+=pr-(mid+1);} while(pr<=r)c[++cnt]=a[pr++]; int k=1; for(int i=l;i<=r;i++)a[i]=c[k++]; return res; } void solve(){ cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; int ans=solve(1,n); //for(int i=1;i<=n;i++)cerr<<a[i]<<" "; cout<<ans<<endl; }

Codeforces Round 656 (Div. 3) D

a-Good String

定义:字符串s 为一个c-好串(c 为一个字符)时,必须满足:

  1. |s|=1s=c

  2. |s|>1, s 的左半部分为全为 c,右半部分为一个 (c+1)-好串 或者 s 的右半部分为全为 c,左半部分为一个 (c+1)-好串

其中 |s| 代表 字符串 s 的长度。

举个例子:当 s=cdbbaaaa"时,s 是一个 a-好串

现在,给你一个字符串 s ( |s|=2k ),问最少替换多少个字符,使其为一个 a-好串

Sol:注意题目给出的字符串长度是特殊的,结合题目意思是非常明显的递归求解暗示。每轮中我们只需要决策是选择前半段作为当前轮字母对应段还是后半段。选择以后,另一段的代码递归求解即可,注意递归边界处理。

string s; int cal(int l,int r,int lev){ int res=0; char c=lev+'a'; if(l==r){ if(s[l]==c)return 0; return 1; } int mid=(l+r)>>1; int c1=0,c2=0; for(int i=l;i<=mid;i++)if(s[i]!=c)c1++; for(int i=mid+1;i<=r;i++)if(s[i]!=c)c2++; res=min(c1+cal(mid+1,r,lev+1),c2+cal(l,mid,lev+1)); return res; } void solve(){ cin>>n; cin>>s; s=" "+s; int ans=cal(1,n,0); cout<<ans<<endl; }

平面最近点对https://www.luogu.com.cn/problem/P1429

P7883 平面最近点对(加强加强版)
给定平面上 n 个点,找出其中的一对点的距离,使得在这 n 个点的所有点对中,该距离为所有点对中最小的
数据保证 0x,y109

Sol:本题存在O(nlogn)的解法,对于排序的复杂度采用归并y来降低https://www.luogu.com.cn/article/aihyptbk,这里先给出朴素的O(n(logn)2)做法

整体思路:以x大小为分界线进行分治,左边内部的最近点对递归解决,右边同理。对于左右交界的贡献,首先考虑横坐标距离分界线大于d无法更新答案,对于这些点按y排序,对于其中一个点,纵坐标距离大于d也不可能更新,可以证明一个点可以用来更新答案的点不超过6个(只考虑中坐标比自己大的点,偏序不重复)。

struct node{ db x,y; bool operator<(const node &A)const{ return x<A.x; } }a[N],c[N]; db dis(node c,node d){ db c1=c.x-d.x,c2=c.y-d.y; return sqrt(c1*c1+c2*c2); } db cal(int l,int r){ if(l==r)return 1e12; int cnt=0;int mid=(l+r)>>1; db d=min(cal(l,mid),cal(mid+1,r)); for(int i=l;i<=r;i++){ if(fabs(a[i].x-a[mid].x)<d){ c[++cnt].y=a[i].x; c[cnt].x=a[i].y; } } sort(c+1,c+1+cnt); for(int i=1;i<=cnt;i++){ for(int j=i+1;j<=cnt&&fabs(c[j].y-c[i].y)<d;j++){ d=min(d,dis(c[i],c[j])); } } return d; } void solve(){ //cerr<<18*18*N<<endl; cin>>n; for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y; sort(a+1,a+1+n); db ans=cal(1,n); baoliu(ans,4); }

__EOF__

本文作者爱飞鱼
本文链接https://www.cnblogs.com/mathiter/p/18199395.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   potential-star  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示