題意:略。
思路:直接二分,因為假設現在在點mid .那麼求出[l , mid]的和,如果是奇數,那麼那個點肯定在前面的區間,也就是mid = r - 1 ,如果是偶數,則證明在後面的區間,mid = l + 1 。然後更新答案即可。
這種解法很容易想到,但是一直T,理論上複雜度完全可以過,一直很不解。
然後發現,二分過程中mid = l + r >> 1 。這個l + r 可能會爆int ,所以mid 值就是負數了,就一直T。
把mid 改成mid = l + (r - l + 1 ) / 2 即可。
細節把握還是太弱了。
#include <set>#include <map>#include <stack>#include <cmath>#include <queue>#include <cstdio>#include <string>#include <vector>#include <iomanip>#include <cstring>#include <iostream>#include <algorithm>#define Max 2505#define FI first#define SE second#define ll long long#define PI acos(-1.0)#define inf 0x7fffffff#define LL(x) ( x << 1 )#define bug puts("here")#define PII pair<int,int>#define RR(x) ( x << 1 | 1 )#define mp(a,b) make_pair(a,b)#define mem(a,b) memset(a,b,sizeof(a))#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )using namespace std;inline void RD(int &ret) { char c ; int flag = 1 ; do { c = getchar() ; if(c == '-')flag = -1 ; } while(c < '0' || c > '9') ; ret = c - '0' ; while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + ( c - '0' ); ret *= flag ;}#define N 22222int A[N] , B[N] , C[N] ;int n ;int main() { while(scanf("%d",&n) != EOF) { int l = inf , r = 0 ; for (int i = 0 ; i < n ; i ++ ) { RD(A[i]) ; RD(B[i]) ; RD(C[i]) ; if(l > A[i]) l = A[i] ; if(r < B[i]) r = B[i] ;// l = min(l , A[i]) ;// r = max(r , B[i]) ; } int ans = inf ; int flag = 0 ; int mid ; while(r >= l) {// mid = l + r >> 1 ; mid = l + (r - l + 1) / 2 ; ll sum = 0 ; for (int i = 0 ; i < n ; i ++ ) { if(C[i] == 0) { if(mid >= A[i]) sum ++ ; continue ; } if(mid >= A[i]) { ll now = min(mid , B[i]) ; sum += (now - A[i]) / C[i] + 1 ; } } if(sum & 1) { r = mid - 1 ; flag = 1 ; if(ans > mid)ans = mid ; } else l = mid + 1 ; } int ss = 0 ; for (int i = 0 ; i < n ; i ++ ) { if(ans <= B[i] && ans >= A[i]) { ss += ((ans - A[i]) % C[i] == 0) ? 1 : 0 ; } } if(!flag)printf("DC Qiang is unhappy.\n") ; else printf("%d %d\n",ans , ss) ; } return 0 ;}