zoukankan      html  css  js  c++  java
  • UVALive

    题目链接:https://vjudge.net/contest/241341#problem/I

    题目大意:输入t,t组样例,输入n,m,有n个圆槽,m个硬币,接下来m行代表每个硬币所在的位子,要求你移动硬币使得相邻的硬币距离相等,输出最小的最大移动步数(这里所指的是

    一个硬币最大移动的步数)

    个人思路:一直在找规律,后来也没有找到,应该是没有规律吧,搜题解也没有搜到有什么规律,全都是用二分来求的。。。这里怎么用二分呢?

    因为数据范围是n<=1e6,并且如果通过单点最大k步移动可以是这些点两两间隔n/m,那么对于任意的k’(k’>k)也一定是可以的。所以可以二分查找需要的最小单点最大移动步数。当单点移动最大步数确定为d时如何判断d是否能使得这些点均匀分布呢?
    考虑每个点的移动区间,假设第i-1个点的移动区间是[prelow,prehigh],因为第i点最多可移动d步,所以第i个点的移动区间是[data[i]-d,data[i]+d],又因为第i-1个点和第i个点需要间隔step=n/m,所以第i-1个点给第i个点的约束移动区间是[prelow+step,prehigh+step],所以第i个点的实际允许移动区间是

    curlow=max(prelow+step,data[i]-d), curhigh=min(prehigh+step,data[i]+d);

    只要对每个点判断这个区间是否存在即curlow<=curhigh是否成立,就能判断d是否合法了。

    看代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<stdio.h>
    #include<string.h>
    #include<cmath>
    #include<math.h>
    #include<algorithm>
    #include<set>
    #include<queue>
    #include<map>
    typedef long long ll;
    using namespace std;
    const ll mod=1e9+7;
    const int maxn=2e4+10;
    const int maxk=100+10;
    const int maxx=1e4+10;
    const ll maxe=1000+10;
    #define INF 0x3f3f3f3f3f3f
    int a[maxn];
    int n,m,step;
    bool solve(int mid)
    {
        int prelow,prehigh,curlow,curhigh;
        prelow=a[0]-mid;
        prehigh=a[0]+mid;
        for(int i=1;i<m;i++)
        {
            curlow=max(prelow+step,a[i]-mid);
            curhigh=min(prehigh+step,a[i]+mid);
            if(curlow>curhigh)
                return false;
            prelow=curlow;
            prehigh=curhigh;
        }
        return true;
    }
    int main()
    {
        int t,sum=1;
        cin>>t;
        while(t--)
        {
            cin>>n>>m;
            for(int i=0;i<m;i++)
            {
                cin>>a[i];
            }
            sort(a,a+m);
            int l=0,r=n;
            step=n/m;
            while(l<r)
            {
                int mid=(l+r)/2;
                if(solve(mid))
                {
                    r=mid;
                }
                else
                    l=mid+1;
            }
            printf("Case #%d: %d
    ",sum++,r);
         //   cout<<r<<endl;
        }
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    oracle修改字符编码
    oracle修改约束列
    oracle非空约束
    Linux修改字符集
    修改oracle字符集合
    word问题禁止宏
    增加修改表列
    oracle增加sequence
    增加 修改oracle约束条件
    oracle用户 密码永不过期
  • 原文地址:https://www.cnblogs.com/caijiaming/p/9386050.html
Copyright © 2011-2022 走看看