《C. Scoring Subsequences》
这道题有很多解法:二分,双指针等,但是无论哪一种都要知道如下:
想要得到当k时,最大的分数,那么就会贪心地将后面的数相乘再除
设长度为len,那么在为k时,长度为len时,max score = (ak*a(k-1)*...*a(k-len+1)/len!
那么在len取何时,在score最大的情况下,len还是最长的?
这里暴力的话,将len枚举,再计算
但是会超时
想一下当len=m与len=m-1的区别
scoreM=(ak*a(k-1)*...*a(k-m+1)/m!
scoreM-1=(ak*a(k-1)*...*a(k-m+2)/(m-1)!
即scoreM-1比scoreM少乘了 a(k-m+1)/m
如果a(k-m+1)/m>1
scoreM-1>scoreM
反之
scoreM-1<scoreM
其余类推
用更数学的方式表示的话就是:
所以在k固定的情况下,对于选取len
即从len=k开始看到len=1,一旦a[k-len+1]/len<1
那么接下来的a[k-len+1]/len必定<1,即我们已经得到答案了
但是这样枚举还是会超时,这里提供两种方法
1.二分法:
二分枚举len,找到那个临界的len就是答案
#include <iostream> #include <algorithm> #include <cstring> #include <queue> using namespace std; void solve() { int n, a[100002]; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= n; i++) { int l = 1, r = i, ans = 0; while (l <= r) { int mid = (l + r) >> 1; if (a[i - mid + 1] / mid >= 1) { ans = mid; l = mid + 1; } else r = mid - 1; } cout << ans << " "; } cout << endl; } int main() { int t; cin >> t; while (t--) solve(); return 0; }
2.用queue:
#include <iostream> #include <algorithm> #include <cstring> #include <queue> using namespace std; void solve() { int n, a[100002]; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; int cnt = 0; queue<int> q; for (int i = 1; i <= n; i++) { q.push(a[i]), cnt++; while (q.size() != 0 && q.front() < cnt) q.pop(), cnt--; cout << cnt << " "; } cout << endl; } int main() { int t; cin >> t; while (t--) solve(); return 0; }
标签:856,int,scoreM,Codeforces,len,mid,solve,Div,include From: https://www.cnblogs.com/cilinmengye/p/17181414.html