zoukankan      html  css  js  c++  java
  • Luogu P4403 [BJWC2008]秦腾与教学评估【二分答案】By cellur925

    题目传送门

    这道题:真·凉心出题人。

    二分答案,个人感觉其实并不只适用于有明显的“最大值最小/最小值最大”条件的题目,其实也可以称它为一种“优化的暴力”。这题就是最好的例子。

    我们肯定可以先想出朴素的算法:把每个点的答案都算出,但是平方级别的复杂度,铁定超时。

    我们考虑用二分优化。这道题的二分其实挺难看出的:因为题目约束奇数人数的点要有也只有一个,也就是说其他有人的点上人数一定为偶数。显然偶数+偶数=偶数,如果没有奇数出现,那么统计的人数和都是偶数。

    我们可以从这个性质出发。二分位置(i),但是二分的不是最终的结果而是一个约束的范围。再具体地说,如果([1,mid])中的人数是奇数那么答案肯定在这个区间中,使(r=mid),否则在右边的区间,即使(l=mid+1)

    因此我们只要统计人数就行了==。

    但是因为一些蜜汁原因,第一次交竟然(T)了。反正在洛谷&&脖子(oj)上捣鼓了半天也是奥妙重重。不过这个题提供的思路还是很棒的。

    奉上阉割版代码。

    #include<cstdio>
    #include<algorithm>
    #define maxn 200090
     
    using namespace std;
    typedef long long ll;
     
    int T,n,ans;
    int s[maxn],e[maxn],d[maxn];
     
    int check(int x)
    {
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(s[i]>x) continue;
            cnt+=(ll)(min(x,e[i])-s[i])/d[i]+1;
        }
        return cnt;
    }
     
    void re(int &x)
    {
        x=0;
        char ch=getchar();
        bool flag=false;
        while(ch<'0'||ch>'9') flag|=(ch=='-'),ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
        x=flag ? -x : x;
    }
     
    int main()
    {
        re(T);
        while(T--)
        {
            re(n);
            for(int i=1;i<=n;i++)
                re(s[i]),re(e[i]),re(d[i]);
            ll l=0,r=2147483647;
            while(l<=r)
            {
                ll mid=(l+r)>>1;
                if(check(mid)&1) r=mid-1,ans=mid;
                else l=mid+1;
            }
            if(!ans) printf("Poor QIN Teng:(
    ");
            else printf("%lld %d
    ",l,check(l)-check(l-1));
            l=1,r=0,ans=0;
        }
        return 0;
    }
    
  • 相关阅读:
    数组最值和两种排序
    整数翻转,99乘法表,百钱买百鸡
    运算符综合练习题
    五子棋实现体验其过程
    二维数组斜线扫描2(方法逻辑清晰)
    字符串链接练习题
    母串中有几个相同的子串
    递归求菲波拉契前N项的和
    [LeetCode] Mini Parser
    Linked List 小结
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9901407.html
Copyright © 2011-2022 走看看