1. 程式人生 > >hdu 6058 To my boyfriend (計算貢獻,思維)

hdu 6058 To my boyfriend (計算貢獻,思維)

時間 () light 區間 frame enc const log --

題意: 給你一個全排列,要你求這個序列的所有區間的第k大的和

思路:比賽的時候一看就知道肯定是算貢獻,也知道是枚舉每個數,然後看他在多少個區間是第K大,然後計算他的貢獻就可以了,但是沒有找到如何在o(k)的時間內找到這k個區間,然後就一直掛機,慘慘慘

感覺官方題解的思路就很棒啊:

我們只要求出對於一個數x左邊最近的k個比他大的和右邊最近k個比他大的,掃一下就可以知道有幾個區間的k大值是x.=

我們考慮從小到大枚舉x,每次維護一個鏈表,鏈表裏只有>=x的數,那麽往左往右找只要暴力跳k次,刪除也是O(1)的。

時間復雜度:O(nk)

代碼:

/** @xigua */
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <cstring>
#include <queue>
#include <set>
#include <string>
#include <map>
#include <climits>
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 5e5 + 5;
const int mod = 1e9 + 9;
const int mod2 = 1e9 + 7;
const int INF = 1e8 + 5;
const ll inf = 1e15 + 5;
const db eps = 1e-5;
const ll hp = 233333;
int a[maxn], pos[maxn], pre[maxn], nex[maxn];
ll pp[105], np[105];

void solve() {
    int n, k; cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        scanf("%d", a + i);
        pos[a[i]] = i;
        pre[i] = i - 1;
        nex[i] = i + 1;
    }
    pre[0] = -1, nex[n+1] = n + 2;
    ll ans = 0;
    for (int i = 1; i <= n; i++) {
        int t1 = 0, t2 = 0;
        int curp = pos[i];
        for (int j = curp; j >= 0 && t1 <= k; j = pre[j]) {
            pp[++t1] = j;
        }
        for (int j = curp; j <= n + 1 && t2 <= k; j = nex[j]) {
            np[++t2] = j;
        }
        for (int j = 1; j <= t1 - 1; j++) {
            if (k - j + 2 > t2) continue;
            ll tmp = (pp[j] - pp[j+1]) * (np[k - j + 2] - np[k - j + 1]);
            ans += tmp * i;
        }
        //刪除當前節點 相當於鏈表
        int tp = pre[curp], tn = nex[curp];
        nex[tp] = tn, pre[tn] = tp;
    }
    cout << ans << endl;
}

int main() {
    int t = 1, cas = 1;
   // freopen("in.txt", "r", stdin);
   // freopen("out.txt", "w", stdout);
   // init();
    scanf("%d", &t);
    while(t--) {
       // printf("Case %d: ", cas++);
        solve();
    }
    return 0;
}

  

hdu 6058 To my boyfriend (計算貢獻,思維)