• 数据读取


    题解:二分答案。用h[]储存磁头位置,p[]储存需要读取的位置。

             在(0,2e10)内找到一个最小值mid使得每个磁头移动mid步能够扫完所有需要读取的位置。

             寻找mid的时候,由三种情况。

                   一 :此时h[i]-p[j]>mid,(即磁头到所需扫描位置大于mid时,说明此时mid比最大步数要小),那么应在(mid+1,r)范围内继续寻找。

                   二:在不符合一的时候,并且p[j]<h[i],(即所需读取位置在磁头左边)则磁头有两种移动方案:

                              由于磁头与左边需要读取的位置的距离为一定值,可先计算出来k=(h[i]-p[j])

                             1:先往左扫描需要扫描的地方,再向右移。此时扫描到的最大位置=p[j]+k;

                             2: 先往右扫描所需扫描的地方,再向左移。此时扫描到的最大位置=h[i]+k/2;

                       此时两种情况取一最大值maxn即为移动mid步时磁头所能到达的最大位置。

                  三:在不符合一的时候,并且p[j]>=h[i],(即所读取的位置在磁头右边)则磁头所能到达的最大位置maxn=p[j]+mid;

           然后根据磁头所能到达的最大位置更新下一个所需读取的位置。若位置j>m时,说明此时mid值能够使得磁头读取完所有需要读取的位置。用ans储存下此时的mid,继续在(l,mid-1)内查找是否有更小值能够满足条件。

    #include<cstdio>
    #include<iostream>
    #define N 100100
    #define ll long long
    using namespace std;
    int n,m;
    ll ans;
    ll h[N],p[N];
    void erfen(ll l,ll r)
    {
        if (l>r) return ;
        bool ff=0;
        ll mid=(l+r)>>1,maxn;
        for (int i=1,j=1;i<=n;i++)
          {
               if (h[i]-p[j]>mid) break;//若此时的磁头与此时需要扫描的位置大于mid,则最大步数应大于mid 
               if (p[j]<h[i])
                 {
                       ll k=mid-(h[i]-p[j]);
                       maxn=max(p[j]+k,h[i]+(k>>1));//注意">>"的运算级比+还低,要加括号 
               }
             else maxn=h[i]+mid;
             while (p[j]<=maxn&&j<=m) j++;
             if (j>m)//此时磁头能够扫完所有需要扫描的位置 
               {
                     ff=1;
                     break;
               }
          }
        if (ff) ans=mid,erfen(l,mid-1);
        else erfen(mid+1,r);
    }
    int main()
    {
        freopen("data.in","r",stdin);
        freopen("data.out","w",stdout); 
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) cin>>h[i];//注意在windows系统下,用scanf("%lld")读取相当于读取int类型的数 
                                         //由于noip考试是在linx系统下进行,此时用scanf读入无问题 
        for (int i=1;i<=m;i++) cin>>p[i];
        ll rr=2e10;
        erfen(0,rr);
        cout<<ans<<endl;
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    二分
  • 相关阅读:
    手工去除 dll 和 exe 文件的数字签名
    针式PKM中级应用:文件的5S(归档整理删除)
    针式PKM初级应用:如何避免收集重复的资料?
    了解更多:什么是个人知识管理?
    如何选用知识管理软件?
    与阿朱聊个人知识管理:体系和方法论层面
    针式PKM初级应用:针式PKM每天应使用多少小时?
    战略人生
    针式PKM初级应用:针式PKM更适合管理什么样的文件
    Data, Information, and Knowledge Management Software "What software should I use?"
  • 原文地址:https://www.cnblogs.com/sjymj/p/5994217.html
Copyright © 2020-2023  润新知