CH0805 防線(算競進階習題)
阿新 • • 發佈:2019-03-22
size con 一道 sin () its memset using char
二分
一道藏的很深的二分題。。。
題目保證只有一個點有奇數個防具,這個是突破口。
因為 奇數+偶數=偶數,我們假設某個點x,如果有奇數點的防具在x的左邊,那麽x的左邊的防具總數一定是奇數,右邊就是偶數
所以我們可以用這個來二分。
至於統計防具的公式,那就是小學學過的等差數列項數=(末項-首項)/公差+1。。
#include <bits/stdc++.h> #define INF 0x3f3f3f3f #define full(a, b) memset(a, b, sizeof a) using namespace std; typedef long long ll; inline int lowbit(int x){ return x & (-x); } inline int read(){ int X = 0, w = 0; char ch = 0; while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); } while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar(); return w ? -X : X; } inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; } inline int lcm(int a, int b){ return a / gcd(a, b) * b; } template<typename T> inline T max(T x, T y, T z){ return max(max(x, y), z); } template<typename T> inline T min(T x, T y, T z){ return min(min(x, y), z); } template<typename A, typename B, typename C> inline A fpow(A x, B p, C lyd){ A ans = 1; for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd; return ans; } const int N = 1e8+5; int s[N], e[N], d[N]; int main(){ int _ = read(); for(; _; _ --){ int n = read(); for(int i = 0; i < n; i ++) s[i] = read(), e[i] = read(), d[i] = read(); int l = 1, r = INF; while(l < r){ int mid = (r + l) >> 1, sum = 0; for(int i = 0; i < n; i ++){ if(s[i] <= mid){ if(e[i] > mid) sum += (mid - s[i]) / d[i] + 1; else sum += (e[i] - s[i]) / d[i] + 1; } } if(sum & 1) r = mid; else l = mid + 1; } int tot = 0; for(int i = 0; i < n; i ++){ if(s[i] <= l && e[i] >= l && (l - s[i]) % d[i] == 0) tot ++; } if(tot == 0) printf("There's no weakness.\n"); else printf("%d %d\n", l, tot); } return 0; }
CH0805 防線(算競進階習題)