HDU 4768 (二分区间---涨姿势)
题意:告诉n组A,B,C,按照A + k * C生成等差数列,问这n组数列中哪个数字出现了奇数次以及出现了几次,题目保证最多只会出现一个这种数字。
分析:读完题并没有思路,后来知道是二分区间,枚举是哪个数字出现了奇数次,算该数字之前一共有几个数字,如果是奇数个,说明答案就在[L , Mid]中。
PS:之前用二分只是枚举具体要求的数字,原来枚举区间也可以,真的涨姿势。二分的时候 l = mid + 1,r = mid ;(一开始r = mid + 1,l = mid就无限循环,手算并没有错啊?很奇怪。。。)
1 #include <cstdio>
2 #include <iostream>
3 #include <sstream>
4 #include <cmath>
5 #include <cstring>
6 #include <cstdlib>
7 #include <string>
8 #include <vector>
9 #include <map>
10 #include <set>
11 #include <queue>
12 #include <stack>
13 #include <algorithm>
14 using namespace std;
15 #define ll long long
16 #define _cle(m, a) memset(m, a, sizeof(m))
17 #define repu(i, a, b) for(int i = a; i < b; i++)
18 #define repd(i, a, b) for(ll i = b; i >= a; i--)
19 #define sfi(n) scanf("%d", &n)
20 #define pfi(n) prllf("%d\n", n)
21 #define INF 0x3f3f3f3f3f
22 #define N 20010
23 ll a[N],b[N],c[N];
24 int n;
25 ll judge(ll p)///p之前已经发了多少张传单了
26 {
27 ll sum = 0;
28 repu(i,0,n)
29 {
30 ll t = min(p,b[i]);
31 if(t >= a[i])
32 sum += ((t - a[i])/c[i] + 1ll);
33 }
34 return sum%2ll;
35 }
36 int main()
37 {
38 while(~scanf("%d",&n))
39 {
40 ll sum = 0ll,t = 0ll,l = INF,r = 0ll;
41 repu(i,0,n)
42 {
43 scanf("%I64d%I64d%I64d",&a[i],&b[i],&c[i]);
44 r = max(r,b[i]);
45 l = min(l,a[i]);
46 }
47 if(!judge(r))
48 {
49 printf("DC Qiang is unhappy.\n");
50 continue;
51 }
52 ll mid = 0ll;
53 while(l < r)
54 {
55 mid = (l + r)/2ll;
56 if(judge(mid))///如果是奇数
57 r = mid ;
58 else
59 l = mid +1ll;
60 }
61 ///求具体有几张
62 sum = 0ll;
63 repu(i,0,n)
64 {
65 if(r >= a[i] && r <= b[i])
66 if((r - a[i])%c[i] == 0)
67 sum++;
68 }
69 printf("%I64d %I64d\n",r,sum);
70 }
71 return 0;
72 }
人生就像心电图,想要一帆风顺,除非game-over