1. 程式人生 > >hihocoder 1483 區間價值

hihocoder 1483 區間價值

題目連結

分析:
肯定不能暴力找。(這不是廢話嘛。。)
稍微思考一下,我們可以發現區間的單調性。當區間寬度變長時,所謂的區間的價值一定會增大。
於是我們先二分答案,然後可以利用區間的單調性判斷答案是否可行。
用Two pointers固定左端點,檢查一段區間的價值是否大於二分值。假設[L, R]這個區間的價值大於了二分的答案,那麼[L, R + 1]……以後的區間都能夠滿足要求。這樣能夠線上性的時間內求出比二分值大的價值的區間數目。
map寄存會TLE,這裡離散化了一下。

#include <iostream>
#include <algorithm>
#include <cstring> using namespace std; const int maxn = 2e5 + 5; long long N, K; int a[maxn], b[maxn], c[maxn]; int f[maxn]; long long check(long long mid) { int p = 1, q = 0; long long ans = 0; long long res = 0; memset(f, 0, sizeof(f)); while (p <= N) { while
(q <= N && res <= mid) { res += 1ll * f[c[++ q]]; f[c[q]] ++; } ans += N - q + 1; f[c[p]] --; res -= 1ll * f[c[p ++]]; } return ans; } int main(int argc, char const *argv[]) { int T; cin>>T; while (T --) { cin
>>N>>K; for (int i = 1; i <= N; i ++) { scanf("%d", a + i); b[i] = a[i]; } sort(b + 1, b + N + 1); int len = unique(b + 1, b + N + 1) - b; for (int i = 1; i <= N; i ++) c[i] = lower_bound(b + 1, b + len + 1, a[i]) - b; long long all = (N + 1) * N / 2; long long lb = 0, ub = 3e12, res = -1; // cout<<"threshold "<<all - K<<endl; while (lb <= ub) { long long mid = (lb + ub) >> 1; long long ans = check(mid); // cout<<mid<<" "<<ans<<endl; if (ans <= all - K) { res = mid; ub = mid - 1; } else lb = mid + 1; } cout<<res<<endl; } return 0; }