HDU 6058 Kanade's sum 逆序求第k大

来源:互联网 发布:什么是算法的复杂性 编辑:程序博客网 时间:2024/06/01 13:39

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6058

题意:给你一个1-n的排列 求所有自子区间的第K大的和

思路:从大到小插入位置 维护当前数位置 以及当前数前面比他大的个数及位置 后面比他大的及位置 所以k=min(n,80) 链表维护  在保证区间有k-1个比当前大的情况 计算贡献 手写链表维护位置

code:

#include<bits/stdc++.h>using namespace std;typedef long long LL;inline void read(int &x){    x = 0;    char p = getchar();    while(!(p <= '9' && p >= '0'))p = getchar();    while(p <= '9' && p >= '0')x *= 10, x += p - 48, p = getchar();}const int MAXN = 5e5 + 10;struct node{    int fro, bac;} pos[MAXN];int a[MAXN], p[MAXN], afro[90], abac[90];int main(){    int t;    read(t);    for(int cas = 1; cas <= t; cas++)    {        int n, k;read(n), read(k);        for(int i = 0; i <= n + 1; i++)  pos[i].fro = 0, pos[i].bac = n + 1;        set<int>s;s.insert(0), s.insert(n + 1);        set<int>::iterator ite;        for(int i = 1; i <= n; i++)        {            read(a[i]);            p[a[i]] = i;        }        LL ans = 0;        for(int i = n; i >= 1; i--)        {            ite = s.lower_bound(p[i]);            int fro = *(--ite), bac = *(++ite);            s.insert(p[i]);            pos[fro].bac  = p[i], pos[p[i]].fro = fro;            pos[p[i]].bac = bac , pos[bac].fro  = p[i];            fro = bac = p[i];            if(i > n - k + 1) continue;            ///计算前k-1 后k-1位置            int fron = 0, bacn = 0;            for(int j = 1; j <= k ; j++)            {                afro[j] = pos[fro].fro;                fro = pos[fro].fro;                if(fro == 0 || fron == k - 1) break;                fron++;            }            for(int j = 1; j <= k; j++)            {                abac[j] = pos[bac].bac;                bac = pos[bac].bac;                if(bac == n + 1 || bacn == k - 1) break;                bacn++;            }            afro[0] = p[i], abac[0] = p[i];            ///计算i对答案的贡献            for(int j = fron; j >= 0; j--)            {                if(k - j - 1 > bacn) break;                LL x1=afro[j] - afro[j + 1],x2=abac[k - j ] - abac[k - j -1],x3=i;                ans += x1*x2*x3;            }        }        printf("%lld\n", ans);    }    return 0;}