cow dating (雙指針)
阿新 • • 發佈:2019-03-18
直接 bitset 時間復雜度 scan ans 寫代碼 一個 最大值 fine
因為最多一只同意,所以我們就可以考慮一個區間哪只同意
對於區間 \([l,r]\),設 \(Pro=\prod\limits_{i=l}^r(1-p[i]),Sum=\sum\limits_{i=l}^r\frac{p[i]}{1-p[i]}\)
答案顯然就是 \(Pro*Sum\)
直接枚舉是 \(O(N^3)\),實測能夠 \(2\) 個點
優化這個式子不是太容易,我們反其道而行之,分析區間
對於 \([l,r]\) 和 \([l,r+1]\) 區間,他們差別也就是多了一個 \(p[r+1]\),那麽如果 \([l,r+1]\) 能夠更新 \([l,r]\),那麽需要滿足
\((Pro*(1-p[r+1])*(\frac{p[r+1]}{1-p[r+1]}+Sum)>Pro*Sum\)
再分析,顯然只有當 \(Sum<1\) 時才能夠更新
顯然加入一個 \(r+1\),後面的 \(Sum\) 肯定會增,那麽就滿足了類似單調性的東西
因為最大間隔的右端時非遞減的,所以我們可以枚舉起點 \(l\),然後掃 \(r\) 就行了
時間復雜度 \(O(n)\)
輸出時轉 int,被卡了一次精度
#include <map> #include <set> #include <ctime> #include <queue> #include <stack> #include <cmath> #include <vector> #include <bitset> #include <cstdio> #include <cctype> #include <string> #include <numeric> #include <cstring> #include <cassert> #include <climits> #include <cstdlib> #include <iostream> #include <algorithm> #include <functional> using namespace std ; //#define int long long ///#define double long double #define rep(i, a, b) for (int i = (a); i <= (b); i++) #define per(i, a, b) for (int i = (a); i >= (b); i--) #define loop(s, v, it) for (s::iterator it = v.begin(); it != v.end(); it++) #define cont(i, x) for (int i = head[x]; i; i = e[i].nxt) #define clr(a) memset(a, 0, sizeof(a)) #define ass(a, sum) memset(a, sum, sizeof(a)) #define lowbit(x) (x & -x) #define all(x) x.begin(), x.end() #define ub upper_bound #define lb lower_bound #define pq priority_queue #define mp make_pair #define pb push_back #define fi first #define se second #define iv inline void #define enter cout << endl #define siz(x) ((int)x.size()) #define file(x) freopen(#x".in", "r", stdin),freopen(#x".out", "w", stdout) typedef long long ll ; typedef unsigned long long ull ; typedef pair <int, int> pii ; typedef vector <int> vi ; typedef vector <pii> vii ; typedef queue <int> qi ; typedef queue <pii> qii ; typedef set <int> si ; typedef map <int, int> mii ; typedef map <string, int> msi ; const int N = 1000010 ; const int INF = 0x3f3f3f3f ; const int iinf = 1 << 30 ; const ll linf = 2e18 ; const int MOD = 1000000007 ; const double eps = 1e-7 ; void print(int x) { cout << x << endl ; exit(0) ; } void PRINT(string x) { cout << x << endl ; exit(0) ; } void douout(double x){ printf("%lf\n", x + 0.0000000001) ; } template <class T> void chmin(T &a, T b) { if (a > b) a = b ; } template <class T> void chmax(T &a, T b) { if (a < b) a = b ; } template <class T> void upd(T &a, T b) { (a += b) %= MOD ; } template <class T> void mul(T &a, T b) { a = 1ll * a * b % MOD ; } int n ; double p[N] ; double ans = -1 ; // 對於 [l,r] 區間,設 P = ∏ i ∈ [l,r] (1-p[i]) // 答案就是 Σi ∈ [l,r] P * p[i] / (1-p[i]) signed main() { // freopen("cowdate.in", "r", stdin) ; // freopen("cowdate.out", "w", stdout) ; scanf("%d", &n) ; rep(i, 1, n) { int x ; scanf("%d", &x) ; p[i] = x * 0.000001 ; } int r = 1 ; double sum = 0, prod = 1 ; rep(l, 1, n) { while (r <= n && sum < 1) { prod *= (1.0 - p[r]) ; sum += p[r] / (1.0 - p[r]) ; r++ ; } ans = max(ans, sum * prod) ; prod /= (1.0 - p[l]) ; sum -= p[l] / (1.0 - p[l]) ; } printf("%d\n", (int) (ans * 1000000)) ; return 0 ; } /* 寫代碼時請註意: 1.ll?數組大小,邊界?數據範圍? 2.精度? 3.特判? 4.至少做一些 思考提醒: 1.最大值最小->二分? 2.可以貪心麽?不行dp可以麽 3.可以優化麽 4.維護區間用什麽數據結構? 5.統計方案是用dp?模了麽? 6.逆向思維?(正難則反) */
cow dating (雙指針)