poj3484 Showstopper 二分

http://poj.org/problem?id=3484


因为题目说至多存在一个奇数点,所以前缀和的奇偶性一定是

偶偶偶偶偶偶偶偶偶偶偶偶偶偶偶偶偶偶偶偶奇奇奇奇奇奇奇奇奇奇奇 的样子

等价于我们要找第一个奇数点,二分该点的坐标来判断即可。


至于判断呢需要以O(n)的时间来找出从1到k的一段的点数,具体实现看代码~

输入格式非常坑,小心数据与数据之间有可能有多个空行。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <cstdio>
#include <algorithm>
#define N 500005
typedef long long LL;
using namespace std;
int n ;
LL X[N] , Y[N] , Z[N];
char str[55];

LL cal(LL k)
{
  LL sum = 0 , x;
  for (int i = 1 ; i <= n; ++ i)
  {
    if (k < X[i]) continue;
    x = min(k , Y[i]);
    sum += (x - X[i]) / Z[i] + 1;
  }
  return sum;
}

void work()
{
  n = 1;
  X[n] = 0;
  sscanf(str , "%I64d %I64d %I64d" , &X[n] , &Y[n] , &Z[n]);
  if (!X[n]) return;
  memset(str , 0 , sizeof(str));
  while (gets(str) , *str)
    ++ n , sscanf(str , "%I64d %I64d %I64d" , &X[n] , &Y[n] , &Z[n]) , memset(str , 0 , sizeof(str));
  LL l = 1 , r = 1LL << 33 , m;
  while (l < r)
  {
    m = (l + r) >> 1;
    if (cal(m) & 1)
      r = m;
    else l = m + 1;
  }
  if (l == 1LL << 33)
    puts("no corruption");
  else printf("%I64d %I64d\n" , l , (cal(l) - cal(l - 1)));
}

int main()
{
  while(gets(str))
    work();
  return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值