zoukankan      html  css  js  c++  java
  • hdu6058[链表维护] 2017多校3

    用一个双向链表来查找比当前元素大的前k-1个元素和后k-1个元素 ,从小到大枚举x,算完x的贡献后将x从链表中删除,优化到O(nk)。

    /*hdu6058[链表维护] 2017多效3*/
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    int T, n, k, temp;
    int pos[500005], pre[500005], nxt[500005];
    LL a[500005], b[500005];
    LL ans = 0;
    LL Getans(int x) {
        int r1 = 0, r2 = 0;
        LL ret = 0;
        for (int i = x; i >= 0 && r1 <= k; i = pre[i]) {
            a[++r1] = i - pre[i];//向前找k-1个比当前元素大的
        }
        for (int i = x; i <= n && r2 <= k; i = nxt[i]) {
            b[++r2] = nxt[i] - i;//向后找k-1个比当前元素大的
        }
        for (int i = 1; i <= r1; i++) {
            if (k - i + 1 <= r2 && k - i + 1 >= 1) {
                //cout << x << ' ' << a[i] << ' ' << b[k - i + 1] << endl;
                ret += a[i] * b[k - i + 1];
            }
        }
        return ret;
    }
    void del(int i) {
        pre[nxt[i]] = pre[i];
        nxt[pre[i]] = nxt[i];
    }
    void connect(int u, int v) {
        nxt[u] = v;
        pre[v] = u;
    }
    void solve() {
        for (int i = 0; i <= n; i++)
            connect(i, i + 1);
        for (int i = 1; i <= n; i++) {
            ans += Getans(pos[i]) * i;
            del(pos[i]);//每次删去一个, 保证其他所有元素都比当前元素大
        }
        printf("%lld
    ", ans);
    }
    int main() {
        scanf("%d", &T);
        while (T--) {
            ans = 0;
            scanf("%d %d", &n, &k);
            for (int i = 1; i <= n; i++) {
                scanf("%d", &temp);
                pos[temp] = i;
            }
            solve();
        }
        return 0;
    }
  • 相关阅读:
    calcite介绍
    kylin介绍
    hbase(三)coprocessor
    流式计算-窗口
    实验室服务器琐事
    流畅的python笔记
    语义分割相关网络简述
    leetcode 696
    树的非递归遍历
    leetcode 665
  • 原文地址:https://www.cnblogs.com/UnderSilenceee/p/7273468.html
Copyright © 2011-2022 走看看