HDU6058 Kanade's sum(链表)

来源:互联网 发布:安卓微信数据恢复 编辑:程序博客网 时间:2024/06/08 15:27

Kanade's sum

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2859    Accepted Submission(s): 1182


Problem Description
Give you an array A[1..n]of length n

Let f(l,r,k) be the k-th largest element of A[l..r].

Specially , f(l,r,k)=0 if rl+1<k.

Give you k , you need to calculate nl=1nr=lf(l,r,k)

There are T test cases.

1T10

kmin(n,80)

A[1..n] is a permutation of [1..n]

n5105
 

Input
There is only one integer T on first line.

For each test case,there are only two integers n,k on first line,and the second line consists of n integers which means the array A[1..n]
 

Output
For each test case,output an integer, which means the answer.
 

Sample Input
15 21 2 3 4 5
 

Sample Output
30
 

Source
2017 Multi-University Training Contest - Team 3 
 

Recommend
liuyiding
 

题意:给一个数组,找到所有区间的第k大数求和

将问题转化一下,可以变为某一个数可以在多少个区间成为第k大数。

对于每一个数x,我们只需要在x的左边找k个比x大的数,x的右边找k个比x大的数,线性扫一遍就能知道有多少个区间包含x而且x是区间第k大。

用链表维护,从小到大枚举所以可以直接删除。


#include <map>#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <queue>using namespace std;const int MAXN=1000100;const int mod=1e9+7;int a[MAXN],pos[MAXN];int pre[MAXN],nxt[MAXN];void del(int x){    pre[nxt[x]]=pre[x];    nxt[pre[x]]=nxt[x];}int n,k;long long L[100],R[100];long long solve(int x){    int l=0,r=0;    //往前跳k步    for(int i=x;i&&l<=k;i=pre[i]){        L[++l]=i-pre[i];//中间距离多少个数    }    //往后跳k步    for(int i=x;i<=n&&r<=k;i=nxt[i]){        R[++r]=nxt[i]-i;    }    long long ans=0;    for(int i=1;i<=l;i++){        if(k-i+1<=r&&k-i+1>=1){            ans+=L[i]*R[k-i+1];        }    }    return ans;}int main(){    int t;    scanf("%d",&t);    while(t--){         scanf("%d%d",&n,&k);         for(int i=1;i<=n;i++){            scanf("%d",a+i);            pos[a[i]]=i;         }         for(int i=0;i<=n+1;i++){            pre[i]=i-1;            nxt[i]=i+1;         }         pre[0]=0,nxt[n+1]=n+1;         long long res=0;         for(int i=1;i<=n;i++){            res+=solve(pos[i])*i;            //因为是从小到大来算的,所以可以直接删除            del(pos[i]);         }         printf("%lld\n",res);    }}





原创粉丝点击