HDU 4768 (二分区间---涨姿势)

题意:告诉n组A,B,C,按照A + k * C生成等差数列,问这n组数列中哪个数字出现了奇数次以及出现了几次,题目保证最多只会出现一个这种数字。

分析:读完题并没有思路,后来知道是二分区间,枚举是哪个数字出现了奇数次,算该数字之前一共有几个数字,如果是奇数个,说明答案就在[L , Mid]中。

PS:之前用二分只是枚举具体要求的数字,原来枚举区间也可以,真的涨姿势。二分的时候 l = mid + 1,r = mid ;(一开始r = mid + 1,l = mid就无限循环,手算并没有错啊?很奇怪。。。)

 #include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
#define ll long long
#define _cle(m, a) memset(m, a, sizeof(m))
#define repu(i, a, b) for(int i = a; i < b; i++)
#define repd(i, a, b) for(ll i = b; i >= a; i--)
#define sfi(n) scanf("%d", &n)
#define pfi(n) prllf("%d\n", n)
#define INF 0x3f3f3f3f3f
#define N 20010
ll a[N],b[N],c[N];
int n;
ll judge(ll p)///p之前已经发了多少张传单了
{
ll sum = ;
repu(i,,n)
{
ll t = min(p,b[i]);
if(t >= a[i])
sum += ((t - a[i])/c[i] + 1ll);
}
return sum%2ll;
}
int main()
{
while(~scanf("%d",&n))
{
ll sum = 0ll,t = 0ll,l = INF,r = 0ll;
repu(i,,n)
{
scanf("%I64d%I64d%I64d",&a[i],&b[i],&c[i]);
r = max(r,b[i]);
l = min(l,a[i]);
}
if(!judge(r))
{
printf("DC Qiang is unhappy.\n");
continue;
}
ll mid = 0ll;
while(l < r)
{
mid = (l + r)/2ll;
if(judge(mid))///如果是奇数
r = mid ;
else
l = mid +1ll;
}
///求具体有几张
sum = 0ll;
repu(i,,n)
{
if(r >= a[i] && r <= b[i])
if((r - a[i])%c[i] == )
sum++;
}
printf("%I64d %I64d\n",r,sum);
}
return ;
}

AC

上一篇:yii2 对象跟数组输出数据到view视图方法


下一篇:linux 一键安装lnmp环境