hiho的每周一题都不会很难,基本上就是一些很裸和经典的问题,这一次写了几道分冶专题的题,做个总结。

分冶最简单的就是二分,二分说简单,很简单,不过7,8行代码,不过也常常写挂,写成无限循环。

直接看题1128

http://hihocoder.com/problemset/problem/1128

很裸的直接二分查找,但是其中的第二种写法,事实上是很不实用的,未排序数组的二分查找,有一丝手写快排的味道,当然这道题直接可以在O(N)的复杂度便历得出结果。每次在2分过程中通过把比x小的数放x左边,把x大的数放x右边的方式,在边排序中边二分查找,效率不比直接排序二分高多少,但思想不错。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
int n,k;
int a[1000005];
int p(int l,int r)
{
int k=a[r];
for(int i=l;i<r;i++)
{
if(a[i]<=a[r])
{
swap(a[i],a[l]);
l++;
}
}
swap(a[l],a[r]);
return l;
} int bs(int *a,int n,int k)
{
int l=0;
int r=n-1;
while(l<=r)
{
int mid=p(l,r);
if(a[mid]==k)
return mid;
else if(a[mid]<k)
l=mid+1;
else
r=mid-1;
}
return -1;
}
int main()
{
scanf("%d %d",&n,&k);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int t=bs(a,n,k);
if(t==-1)
printf("%d\n",t);
else
printf("%d\n",t+1);
}

1133这道题http://hihocoder.com/problemset/problem/1133

找第k小的数

滚动数组,也算是手排加二分吧。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
int n,k,c;
int a[2][1000005];
int p(int l,int r,int c)
{
int k=a[1-c][r];
int lf=l;
int rf=r;
for(int i=l;i<r;i++)
{
if(a[1-c][i]<k)
{
a[c][lf++]=a[1-c][i];
}
else if(a[1-c][i]>k)
{
a[c][rf--]=a[1-c][i];
}
a[c][lf]=k;
}
return lf;
} int bs(int n,int k)
{
int l=0;
int r=n-1;
c=1;
while(l<=r)
{
int mid=p(l,r,c);
if(l==r)
c=1-c;
if(mid==k)
return a[c][mid];
else if(mid<k)
l=mid+1;
else
r=mid-1;
c=1-c;
}
return -1;
} int main()
{
scanf("%d %d",&n,&k);
for(int i=0;i<n;i++)
{
scanf("%d",&a[0][i]);
}
int t=bs(n,k-1);
printf("%d\n",t);
}

1139http://hihocoder.com/problemset/problem/1139

二分判断,每次二分判断是否能符合题目的要求,这道题让我重新回忆了如何链式前向星建图,由于bfs O(N+E)的复杂度完全可以接受,就直接bfs搞起,写的很不熟练,也码了很长时间。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long
int n,m,k,kk,u,v,w;
int head[10005];
int vis[10005];
int cnt=0;
struct edge
{
int v,w,next;
edge() {};
edge(int x,int y,int ww):v(x),w(y),next(ww){};
}e[200005]; struct node
{
int u,cc;
node() {};
node(int x,int y):u(x),cc(y){};
};
queue<node> q;
void add_edge(int u,int v,int w)
{
e[cnt]=edge(v,w,head[u]);
head[u]=cnt++;
} bool bfs(int key)
{
// printf("cas %d\n",key);
memset(vis,0,sizeof(vis));
while(!q.empty())
q.pop();
q.push(node(1,0));
vis[1]=1;
while(!q.empty())
{
node t=q.front();
q.pop();
for(int xx=head[t.u];xx!=-1;xx=e[xx].next)
{
int v=e[xx].v;
if(e[xx].w<=key&&t.cc+1<=k)
{
if(v==kk)
return 1;
if(vis[v])
continue;
q.push(node(v,t.cc+1));
vis[v]=1;
}
}
}
return 0;
} int main()
{
// freopen("input.txt","r",stdin);
memset(head,-1,sizeof(head));
scanf("%d%d%d%d",&n,&m,&k,&kk);
int mm=-1;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
mm=max(w,mm);
}
if(n==1)
{
printf("0\n");
return 0;
}
int l=0,r=mm;
while(l<r)
{
int mid=(r+l)/2;
if(bfs(mid))
{
r=mid;
}
else
l=mid+1;
}
printf("%d\n",l);
}

1141http://hihocoder.com/problemset/problem/1141

逆序对,老问题,常用方法就归并排序和树状数组,这两个方法都写一次。

并归排序就是先通过递归二分,再合并,类似后序便历,然后在合并的过程中求出逆序对的个数。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long
int n;
int a[100005];
int temp[100005];
ll res=0;
void pp(int l,int mid,int r)
{
int lf=l,rf=mid,ls=mid+1,rs=r;
int ans=0;
while(lf<=rf&&ls<=rs)
{
if(a[lf]<=a[ls])
{
temp[ans++]=a[lf++];
res+=(ls-mid-1);
}
else
{
temp[ans++]=a[ls++];
}
}
while(lf<=rf)
{
temp[ans++]=a[lf++];
res+=(ls-mid-1);
}
while(ls<=rs)
{
temp[ans++]=a[ls++];
}
for(int i=0;i<ans;i++)
a[l+i]=temp[i];
} void merge_sort(int l,int r)
{
if(l<r)
{
int mid=(l+r)/2;
merge_sort(l,mid);
merge_sort(mid+1,r);
pp(l,mid,r);
}
} int main()
{
//freopen("input.txt","r",stdin);
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
merge_sort(0,n-1);
cout<<res<<endl;
}

树状数组:

树状数组就是这样的一种数据结构,原理类似多重背包的二进制做法,都把O(N)的复杂度简化到log的复杂度。

目前只会单点修改,查询区间。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
#include<set>
using namespace std;
#define ll long long
int n; struct node
{
int pos,val,cc;
}a[100005];
int r[100005];
int c[100005];
bool cmp(node a,node b)
{
return a.val<b.val;
} int lowbit(int x)
{
return x&(-x);
} void add(int i,int v)
{
while(i<=n)
{
c[i]+=v;
i+=lowbit(i);
}
} ll getsum(int x)
{
ll sum=0;
while(x)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
int main()
{
//freopen("a+b.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].val);
a[i].pos=i;
}
sort(a+1,a+n+1,cmp);
r[a[1].pos]=1;
for(int i=2;i<=n;i++)
{
if(a[i].val==a[i-1].val)
r[a[i].pos]=r[a[i-1].pos];
else
r[a[i].pos]=r[a[i-1].pos]+1;
}
ll ans=0;
for(int i=1;i<=n;i++)
{
add(r[i],1);
ans+=i-getsum(r[i]);
}
cout<<ans<<endl;
}

注意离散化的时候同样大的数值一样。

1142 三分

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long
int a,b,c,x,y;
const double eps=1e-8;
double dis(double xx)
{
double yy=(a*xx*xx+b*xx+c);
return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
} int main()
{
//freopen("input.txt","r",stdin);
scanf("%d%d%d%d%d",&a,&b,&c,&x,&y);
double lf=-200,rf=200,midf,midr;
while(rf-lf>eps){
midf=(lf*2+rf)/3;
midr=(lf+rf*2)/3;
if(dis(midf)<dis(midr))
rf=midr;
else
lf=midf;
}
printf("%.3f\n",dis(lf));
}

简单的说啊,首尾a,b;取两个三分点,然后如果求最小值,答案肯定包括小的那一段,求最大值,包括大的那一段。

hiho 分冶专题的更多相关文章

  1. Leetcode之分治法专题-169. 求众数(Majority Element)

    Leetcode之分治法专题-169. 求众数(Majority Element) 给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是 ...

  2. Leetcode之分治法专题-654. 最大二叉树(Maximum Binary Tree)

    Leetcode之分治法专题-654. 最大二叉树(Maximum Binary Tree) 给定一个不含重复元素的整数数组.一个以此数组构建的最大二叉树定义如下: 二叉树的根是数组中的最大元素. 左 ...

  3. hiho拓扑排序专题 ——第四十八、四十七周

    拓扑排序·一 分析: 此题就是求一个有向图中是否存在环. 如存在环则输出"Wrong", 若不存在环, 说明课程安排的合理,输出"Correct". 题中的提示 ...

  4. Leetcode Kth Smallest Element in a BST

    Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. Not ...

  5. 逆序数 POJ 2299 Ultra-QuickSort

    题目传送门 /* 题意:就是要求冒泡排序的交换次数. 逆序数:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序. 一个排列中逆序的总数就称为这个排列的逆 ...

  6. 【NOI2005】维护数列

    https://daniu.luogu.org/problem/show?pid=2042 一道伸展树维护数列的很悲伤的题目,共要维护两个标记和两个数列信息,为了维护MAX-SUM还要维护从左端开始的 ...

  7. vuex的使用及持久化state的方式

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 当我们接触vuex的时候,这是我们最先看到 ...

  8. LeetCode 4. Median of Two Sorted Arrays & 归并排序

    Median of Two Sorted Arrays 搜索时间复杂度的时候,看到归并排序比较适合这个题目.中位数直接取即可,所以重点是排序. 再来看看治阶段,我们需要将两个已经有序的子序列合并成一个 ...

  9. vuex的使用及持久化state的方式详解

    vuex的使用及持久化state的方式详解 转载  更新时间:2018年01月23日 09:09:37   作者:baby格鲁特    我要评论 这篇文章主要介绍了vuex的使用及持久化state的方 ...

随机推荐

  1. 1218.3——init自定义

    相当于构造方法,有的时候初始化的时候有一些默认值,还有就是页面加载数据的时机问题,防止加载了页面再填数据 声明: -(instancetype)initWithName:(NSString *)aNa ...

  2. Webfrom基础知识

    MyBeNASP.NET内置对象 (1)简述ASP.NET内置对象. 答:ASP.NET提供了内置对象有Page.Request.Response.Application.Session.Server ...

  3. Struts 2读书笔记-----Action访问Servlet API

    Action访问Servlet API Struts2中的Action并没有和任何Servlet API耦合,这样框架更具灵活性,更易测试. 对于Web应用的控制器而言,不访问ServletAPI是几 ...

  4. VC++ 控制台不自动退出

    1.Ctrl+F5 2.结尾添加 getchar() 3.结尾添加 system("pause"); 参考:http://jingyan.baidu.com/article/555 ...

  5. QT错误:collect2:ld returned 1 exit status

    1.编译成功的例子在后台执行,有时一闪而过,如果再次build ,则会提示上述错误. 解决方法:打开任务管理器,找到相应的exe进程,关闭即可:  或者直接关闭QtCreator. 2.没有编译成功的 ...

  6. Mysql常用命令行大全(转)

    第一招.mysql服务的启动和停止 net stop mysql net start mysql 第二招.登陆mysql 语法如下: mysql -u用户名 -p用户密码 键入命令mysql -uro ...

  7. jq里attr和prop的区别

    jquery中attr和prop的区别   在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答 ...

  8. 前端开发者使用JS框架的三个等级

    目前前端开发者使用JS框架是种很普遍的现象,因为框架可以加快开发速度,同时避免各类浏览器的兼容性问题.不过同样是用框架开发,不同开发者的境界水平还是有一定差距,本文将这些前端开发者分为三个等级. 第一 ...

  9. python 连接操作数据库(二)

    一.我们接着上期的博客继续对ORM框架进行补充,顺便把paramiko模块也给大家讲解一下: 1.ORM框架: 在连接操作数据库的第一个博客中也已经说了,sqlalchemy是一个ORM框架,总结就是 ...

  10. 闲聊之Python的数据类型 - 零基础入门学习Python005

    闲聊之Python的数据类型 让编程改变世界 Change the world by program Python的数据类型 闲聊之Python的数据类型所谓闲聊,goosip,就是屁大点事可以咱聊上 ...