HDU-2017 多校训练赛3-1003-Kanade’s sum

来源:互联网 发布:河南统计网络直报平台 编辑:程序博客网 时间:2024/06/02 19:14

ACM模版

描述

描述

题解

我的意中人是个盖世英雄,有一天他会踩着七色的云彩来娶我,我猜中了开头,可是我猜不着这结局……

这个题我也是猜中了开头,却没有猜中结尾……

首先,很明显的一个条件是,人家要求所有子区间的第 k 大的值的和,那么,很明显我们不能求所有子区间,我们必须求每个值的贡献才行。这个故事的开头总是如此,很容易猜到……

然后我就各种想,怎么才能优化这个贡献的查询呢?单调栈肯定不行,暴力,更不行……想来想去,始终无法使程序更优,也就 TLE 到了最后。

后来,发现这个题想要优化到 O(nk) 并非难事,因为我们想要求一个值的贡献,只需要求出一个值左边比他大的 k1 个数,右边也求出比他大的 k1 个数,就这样,我们就能求出来他的贡献,这部分比赛时就很清楚,但是没有想到一个很重要的优化,那就是从小到大进行枚举,维护一个链表,链表中的每个数都是比这个枚举的数要大的,所以我们只需要 O(k) 复杂度就能求出来这个数的左右范围,最后复杂度自然就是 O(nk),哎,感觉我自己好愚蠢,这么常见的优化我竟然没有想到……

代码

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;typedef long long ll;const int MAXN = 5e5 + 10;template <class T>inline void scan_d(T &ret){    char c;    ret = 0;    while ((c = getchar()) < '0' || c > '9');    while (c >= '0' && c <= '9')    {        ret = ret * 10 + (c - '0'), c = getchar();    }}int n, k;int s0, t0;ll ans = 0;int a[MAXN], pos[MAXN];int pre[MAXN], ntp[MAXN];int s[MAXN], t[MAXN];void erase(int x){    int pp = pre[x];    int nn = ntp[x];    if (pre[x])    {        ntp[pre[x]] = nn;    }    if (ntp[x] <= n)    {        pre[ntp[x]] = pp;    }    pre[x] = ntp[x] = 0;}void solve(){    for (int i = 1; i <= n; i++)    {        pre[i] = i - 1;        ntp[i] = i + 1;    }    ans = 0;    for (int num = 1; num <= n - k + 1; num++)    {        int p = pos[num];        s0 = t0 = 0;        for (int d = p; d && s0 <= k + 1; d = pre[d])        {            s[++s0] = d;        }        for (int d = p; d != n + 1 && t0 <= k + 1; d = ntp[d])        {            t[++t0] = d;        }        s[++s0] = 0;        t[++t0] = n + 1;        for (int i = 1; i < s0; i++)        {            if (k + 1 - i <= t0 - 1 && k + 1 - i >= 1)            {                ans += (t[k + 1 - i + 1] - t[k + 1 - i]) * 1ll * (s[i] - s[i + 1]) * num;            }        }        erase(p);    }}int main(){    int T;    scan_d(T);    while (T--)    {        scan_d(n), scan_d(k);        for (int i = 1; i <= n; i++)        {            scan_d(a[i]);            pos[a[i]] = i;        }        solve();        cout << ans << endl;    }    return 0;}
原创粉丝点击