zoukankan      html  css  js  c++  java
  • CF 949D Curfew——贪心(思路!!!)

    题目:http://codeforces.com/contest/949/problem/D

    有二分答案的思路。

    如果二分了一个答案,首先可知越靠中间的应该大约越容易满足,因为方便把别的房间的人聚集过来;所以如果二分了答案为 f ,可以认为合法的房间是除了前 f 个和后 f 个的剩下的房间。

    但边缘房间自己能满足时也不用专门往中间跑,但一旦要跑,方向一定是向中间的;所以可以用指针判断;

    可以认为 f 是合法房间的一个界限;指针走的时候累计一下已经有多少人,当又满足一个房间时,如果指针在界限 f 之前,说明指针后面的房间的人都不用动;而指针前面房间的人一定能赶上跑到那个房间(最差就是被挤着一个一个房间地走),所以不会在时间上不合法;如果指针在界限 f 之后,说明界限到指针之间房间的相应人数要跑到界限这个房间(每次合法一对房间(前面和后面一起做),界限向中间移动一格),这时要判断一下时间来得及否;时间就是从开头到查到界限 f 这个房间的总用时(从题解上可以看出题意好像是先跑一个单位时间,然后再查一个单位时间;即查 i 房间之前有 i 个单位时间)。

    如果一直没有不合法,因为是按人数调指针的,所以一定恰好弄完所有人,最后就是合法的。

    先放一份cf上的有自己注释的题解代码:

    #include <iostream>
    #include <string>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    #define FOR(i,a,b) for (int i = (a); i < (b); i++)
    #define SZ(a) a.size()
    #define LL long long
    
    const LL mod = 1000000007;
    
    int n,d,b;
    int a[200000];
    int A[200000];
    
    bool ok(int num)
    {
        FOR (i,0,n) A[i] = a[i];
        LL f1 = num, f2 = n-num-1, s1 = 0, s2 = n-1;
        //f1:左边第一个需要合法的(从0标号) f2:右边第一个需要合法的
        while (f1 < f2)
        {
            int val, N;
            N = b;
            while (N && s1-f1 <= 1LL*d*(f1+1)) {val = min(A[s1],N), N-= val, A[s1] -= val; if (A[s1] == 0) s1++;}
            if (N) return false;//查完一个合法房间
            //s1>f1怎么理解?s1与s2的相交呢?
            //s1不会与s2相交。因为它是看人数的。做完(n+1)/2个N的消耗后,所有a刚好被用完,s1与s2在同一个点
            //s1>f1也不怕,因为f1和f2只是一个计时的东西。最后s1和s2的交点是自己合法房间分布的中心
            //上一行不太对。因为只要合法房间分布的中心不在所有房间的中心,即意味着有一个宿管超额了
            //应当认为越靠中心越容易被满足(大约),s1>f1意味着从后面找人走过来
            //s1是指针,就能前一段给f1,之后一段给f1+1……这样贪心
            //其实f1的意义是保证f1和它前面的点中这一回有一个合法房间。s1<=f1时相当于没记时间,就是这个意思,
            //为了不浪费边界房间
            N = b;
            while (N && f2-s2 <= 1LL*d*(f1+1)) {val = min(A[s2],N), N-= val, A[s2] -= val; if (A[s2] == 0) s2--;}
            if (N) return false;
            f1++; f2--;//自己剩余的合法限度(一旦某个房间合法的过程中使得后面没有足够房间,就崩)
            //没有上述情况地做到最后,因为总人数是符合的,所以可以满足
        }
        return true;
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&d,&b);
        //n = 4; d = 3; b = 1; a[0] = n*b;
        FOR (i,0,n) scanf("%d",a+i);
        int l = 0, r = (n+1)/2;
        while (l != r)
        {
            int x = (l+r)/2;
            if (ok(x)) r = x;
            else l = x+1;
        }
        cout << l;
    }
    View Code

    再放上自己的学习(抄)成果:(注意a数组会改变,要每次赋回原值)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=1e5+5;
    int n,d,b,lm,a[N],c[N],l,r,ans,p0,p1,s;
    ll dis;
    int rdn()
    {
        int ret=0;bool fx=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
        while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
        return fx?ret:-ret;
    }
    bool check(int f)
    {
        dis=(ll)d*f; p0=1; p1=n;
        for(int i=f+1;i<=lm;i++)
        {
            dis+=d;
            
            s=b;
            while(a[p0]<s)s-=a[p0++]; a[p0]-=s;
            if(p0-i>dis)return 0;
    
            if(i==lm&&(n&1))break;
            s=b;
            while(a[p1]<s)s-=a[p1--]; a[p1]-=s;
            if((n-i+1)-p1>dis)return 0;
        }
        return 1;
    }
    int main()
    {
        n=rdn(); d=rdn(); b=rdn(); lm=(n+1)>>1;
        for(int i=1;i<=n;i++) c[i]=a[i]=rdn();
        l=0; r=n+1;
        while(l<=r)
        {
            int mid=l+r>>1;
            memcpy(a,c,sizeof c);
            if(check(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    分享最好的HTML5编码教程和参考手册
    随机字符变换效果的jQuery插件开发教程
    拒绝用SEO的眼光来设计你的Meta标签
    GBin1教程:使用jQuery插件jquery.validationEngine实现表单验证功能
    vs 2010 程序发布时出现 TransformXml任务意外失败
    CSS hack
    javascript div 弹出可拖动窗口
    Javascript String类的属性及方法
    兼容浏览器的布局CSS
    该伙伴事务管理器已经禁止了它对远程/网络事务的支持
  • 原文地址:https://www.cnblogs.com/Narh/p/9706060.html
Copyright © 2011-2022 走看看