【算法提高——第六讲】基础算法(2)

简介: 【算法提高——第六讲】基础算法(2)

6.4 二分

6.4.1 102. 最佳牛围栏

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,F;
double a[N],s[N];
bool check(double avg)
{
    for(int i=1;i<=n;i++)
        s[i]=s[i-1]+a[i]-avg;
    double mins=0;
    for(int k=F;k<=n;k++)
    {
        mins=min(mins,s[k-F]);
        if(s[k]-mins>=0)
            return true;
    }
    return false;
}
int main()
{
    cin>>n>>F;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    double l=0,r=2000;
    while(r-l>1e-5)
    {
        double mid=(l+r)/2;
        if(check(mid)) l=mid;
        else r=mid;
    }
    cout<<(int)(r*1000)<<endl;
    return 0;
}

6.4.2 113. 特殊排序

image.png


代码:


// Forward declaration of compare API.
// bool compare(int a, int b);
// return bool means whether a is less than b.
class Solution {
public:
    vector<int> specialSort(int N) {
    vector<int> res(1,1);
        for(int i=2;i<=N;i++)
        {
            int l=0,r=res.size()-1;
            while(l<r)
            {
                int mid=l+r+1>>1;
                if(compare(res[mid],i)) l=mid;
                else r=mid-1;
            }
            res.push_back(i);
            for(int j=res.size()-2;j>r;j--)
                swap(res[j],res[j+1]);
            if(compare(i,res[r]))
                swap(res[r],res[r+1]);
        }
        return res;
    }
};

6.5 排序

6.5.1 105. 七夕祭

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100010;
int n,m,t;
int row[N],col[N],s[N],c[N];
int work(int n,int a[])
{
    for(int i=1;i<=n;i++)
        s[i]=s[i-1]+a[i];
    if(s[n]%n) return -1;
    int avg=s[n]/n;
    for(int i=1;i<=n;i++)
        c[i]=s[i-1]-(i-1)*avg;
    sort(c+1,c+n+1);
    LL res=0;
    for(int i=1;i<=n;i++)
        res+=abs(c[i]-c[(n+1)/2]);
    return res;
}
int main()
{
    cin>>n>>m>>t;
    for(int i=0;i<t;i++)
    {
        int x,y;
        cin>>x>>y;
        row[x]++,col[y]++;
    }
    LL r=work(n,row);
    LL c=work(m,col);
    if(r!=-1&&c!=-1) cout<<"both "<<r+c<<endl;
    else if(r!=-1) cout<<"row "<<r<<endl;
    else if(c!=-1) cout<<"column "<<c<<endl;
    else cout<<"impossible"<<endl;
    return 0;
}

6.5.2 106. 动态中位数

image.png


代码:


// 对顶堆
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
int p,id,m;
int ans[N],cnt;
int main()
{
    cin>>p;
    while(p--)
    {
        priority_queue<int> down;   //大根堆,放较小数,个数比小根堆多一
        priority_queue<int,vector<int>,greater<int> > up;   //小根堆,放较大数
        cnt=1;
        cin>>id>>m;
        for(int i=1;i<=m;i++)
        {
            int x;
            cin>>x;
            if(down.size()==0||down.top()>=x)
                down.push(x);
            else up.push(x);
            if(up.size()>=down.size())  //调整堆元素数量
            {
                down.push(up.top());
                up.pop();
            }
            if(up.size()+1<down.size()) //调整堆元素数量
            {
                up.push(down.top());
                down.pop();
            }
            if(i%2)
                ans[cnt++]=down.top();
        }
        cout<<id<<" "<<cnt-1<<endl;
        for(int i=1;i<cnt;i++)
        {
            if(i%10==0)
                cout<<ans[i]<<endl;
            else
                cout<<ans[i]<<" ";
        }
        if((cnt-1)%10)
            cout<<endl;
    }
    return 0;
}
/* 二分插入法
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
int p,id,m;
vector<int> a;
int ans[N],cnt;
//整数二分,得到第一个小于等于x的下标
int get(int x)
{
    int l=0,r=a.size();
    while(l<r)
    {
        int mid=l+r>>1;
        if(a[mid]>=x) r=mid;
        else l=mid+1;
    }
    return r;
}
int main()
{
    cin>>p;
    while(p--)
    {
        a.clear();
        a.push_back(-1e9);
        cnt=1;
        cin>>id>>m;
        for(int i=1;i<=m;i++)
        {
            int x;
            cin>>x;
            if(i==1)
                a.push_back(x);
            else
            {
                int k=get(x);
                a.insert(a.begin()+k,x);
            }
            if(i%2)
                ans[cnt++]=a[(i+1)/2];
        }
        cout<<id<<" "<<cnt-1<<endl;
        for(int i=1;i<cnt;i++)
        {
            if(i%10==0)
                cout<<ans[i]<<endl;
            else
                cout<<ans[i]<<" ";
        }
        if((cnt-1)%10)
            cout<<endl;
    }
    return 0;
}
*/

6.5.3 107. 超快速排序

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=500010;
int n;
int a[N],temp[N];
LL merge_sort(int q[],int l,int r)
{
    if(l>=r)
        return 0;
    int mid=l+r>>1;
    LL res=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])
            temp[k++]=q[i++];
        else
        {
            res+=mid-i+1;
            temp[k++]=q[j++];
        }
    }
    while(i<=mid)
    {
        temp[k++]=q[i++];
    }
    while(j<=r)
    {
        temp[k++]=q[j++];
    }
    for(i=l,j=0;i<=r;i++,j++)
    {
        q[i]=temp[j];
    }
    return res;
}
int main()
{
    while(true)
    {
        cin>>n;
        if(n==0) break;
        for(int i=0;i<n;i++)
            cin>>a[i];
        cout<<merge_sort(a,0,n-1)<<endl;
    }
    return 0;
}

6.6 RMQ

6.6.1 1273. 天才的记忆

image.png


代码:


// RMQ解法
#include<bits/stdc++.h>
using namespace std;
const int N=200010,M=18;
int n,m;
int w[N];
int f[N][M];
void init()
{
    for(int j=0;j<M;j++)
    {
        for(int i=1;i+(1<<j)-1<=n;i++)
        {
            if(!j) f[i][j]=w[i];
            else f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
        }
    }
}
int query(int l,int r)
{
    int len=r-l+1;
    int k=log(len)/log(2);
    return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>w[i];
    init();
    cin>>m;
    while(m--)
    {
        int l,r;
        cin>>l>>r;
        cout<<query(l,r)<<endl;
    }
    return 0;
}
/*线段树解法 注意INF取值
#include<bits/stdc++.h>
using namespace std;
const int N=200010,INF=0x3f3f3f3f;
int n,m;
int w[N];
struct Node
{
    int l,r;
    int v;  // 区间[l, r]中的最大值
    Node(){}
    Node(int _l,int _r,int _v)
    {
        l=_l,r=_r,v=_v;
    }
}tr[4*N];
void pushup(int u)  // 由子节点的信息,来计算父节点的信息 u表示父节点编号
{
    tr[u].v=max(tr[u<<1].v,tr[u<<1|1].v);
}
void build(int u,int l,int r)   //u表示父节点编号,从u开始建立[l,r]的线段树
{
    tr[u]=Node(l,r,w[r]);
    if(l==r) return;
    int mid=l+r>>1;
    build(u<<1,l,mid),build(u<<1|1,mid+1,r);
    pushup(u);
}
int query(int u,int l,int r)
{
    if(tr[u].l>=l&&tr[u].r<=r) return tr[u].v; // 树中节点,已经被完全包含在[l, r]中了
    int mid=tr[u].l+tr[u].r>>1;
    //注意初值
    int v=-INF;
    if(l<=mid) v=query(u<<1,l,r);
    if(r>mid) v=max(v,query(u<<1|1,l,r));
    return v;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>w[i];
    build(1,1,n);
    cin>>m;
    while(m--)
    {
        int a,b;
        cin>>a>>b;
        cout<<query(1,a,b)<<endl;
    }
    return 0;
}
*/

相关文章
|
7天前
|
算法
基础算法题
基础算法编程题
10 3
|
算法 C++
【基础算法】开平方算法 & C++实现
在数学中,因为很多数的开平方都是无理数,所以我们需要借助数值计算的方式来进行近似值的求解。
248 0
【基础算法】开平方算法 & C++实现
|
11月前
|
算法 C++
算法基础课
算法基础课
|
11月前
|
存储 算法 大数据
基础算法-高精度乘法
高精度算法 为什么要使用高精度算法 C++ 每一个变量都有自己的类型,每个类型都有自己的存储长度范围
|
存储 人工智能 算法
【有营养的算法笔记】基础算法 —— 高精度算法(加减乘除)2
【有营养的算法笔记】基础算法 —— 高精度算法(加减乘除)
84 0
【有营养的算法笔记】基础算法 —— 高精度算法(加减乘除)2
|
存储 人工智能 算法
【有营养的算法笔记】基础算法 —— 高精度算法(加减乘除)
【有营养的算法笔记】基础算法 —— 高精度算法(加减乘除)
152 0
【有营养的算法笔记】基础算法 —— 高精度算法(加减乘除)
|
算法 C++
|
存储 算法 C++
基础算法。。。
基础算法。。。
58 0
|
算法
基础算法练习200题07、编框
基础算法练习200题07、编框
59 0
|
算法
基础算法练习200题11、鸡兔同笼
基础算法练习200题11、鸡兔同笼
92 0
基础算法练习200题11、鸡兔同笼