HDU2607 Let the Balloon Rise II 二分

Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=2607


【题意】


给定一种数据压缩的格式,

比如1、10、2,表示从1开始,相隔为2且小于10的数的集合,即1、3、5、7、9。

给定n组数据,求所有数中出现次数为奇数的唯一一个数是多少及出现的次数。或者所有数出现次数都为偶数。


【思路】


二分。

下界为所有开始的数的最小值减一。

上届为可能取得的最大的数加一。

对于某个数,求出位于它左边的所有数的次数。

若为奇数,则继续二分计算其左边。

否则二分计算其右边。(或者同时计算出其右边,若左右同为偶数则说明不存在这样的数)

得到该数后再扫描一遍计算其次数。

我承认因为忘了改成_int64而TLE了无数次= =

巨恶心的还有它的输入格式,居然是以n多空行间隔case的,而且文件结尾也扑朔迷离,在TLE无数的情况下确实给我增加了不少压力!


【代码】


#include <iostream>
using namespace std;

const int maxn = 50000;

__int64 a[maxn+5], b[maxn+5], c[maxn+5];
__int64 d[maxn+5];
char str[maxn+5];

inline __int64 max(__int64 a, __int64 b)
{
    if (a>=b) return a;
    else return b;
}

inline __int64 min(__int64 a, __int64 b)
{
    if (a<=b) return a;
    else return b;
}

inline __int64 get(__int64 x, __int64 y, __int64 z)
{
    return (y-x)/z+1;
}

int solve(__int64 mid, int n)
{
    int i;
    int al = 0, ar = 0;
    int t, ct;
    for (i=0; i<n; i++)
    {
        ct = 0;
        if (mid>=a[i])
        {
            t = min(mid, b[i]);
            ct += get(a[i], t, c[i]);
        }
        al += ct;
        ar += d[i] - ct;
    }
    if (al%2==1) return 1;
    else if (ar%2==1) return -1;
    else return 0;
}

int main()
{
    int i;
    int n;
    __int64 low, high, mid;
	__int64 ans, act;
    bool flag = true;
    while(flag)
    {
        i = 0;
        flag = false;
        while(gets(str) && (flag=true))
        {
            if (str[0]>='0' && str[0]<='9') break;
            flag = false;
        }
        if (!flag) break;
		flag = false;
        do
        {
            sscanf(str, "%d %d %d", &a[i], &b[i], &c[i]);
            i++;
			flag = false;
        }while(gets(str) && (flag=true) && str[0]>='0' && str[0]<='9');
        n = i;
        for (i=0; i<n; i++) d[i] = get(a[i], b[i], c[i]);
        low = (__int64)INT_MAX*2;
        high = (__int64)INT_MIN;
        for (i=0; i<n; i++)
        {
            low = min(low, a[i]);
            high = max(high, (d[i]-1)*c[i]+a[i]);
        }
        low--;
        high++;
        bool f = false;
        while(low<=high)
        {
            mid = (low+high)>>1;
            switch(solve(mid, n))
            {
            case -1:
                low = mid + 1;
                break;
            case 0:
                f = true;
                break;
            case 1:
                ans = mid;
                high = mid-1;
                break;
            }
            if (f) break;
        }
        if (f) printf("None.\n");
        else
        {
            act = 0;
            for (i=0; i<n; i++)
            {
                if (ans>=a[i] && ans<=b[i] && (ans-a[i])%c[i]==0)
                    act++;
            }
            printf("%I64d %I64d\n", ans, act);
        }
    }
    return 0;
}


你可能感兴趣的:(HDU2607 Let the Balloon Rise II 二分)