HDOJ 6085-Kanade's sum

来源:互联网 发布:腾讯视频评论源码 编辑:程序博客网 时间:2024/06/08 02:10

Kanade's sum

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 2161    Accepted Submission(s): 879


题目链接:点击打开链接

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
1


5 2


1 2 3 4 5
 


Sample Output
30



题意:数列A[1....n]的长度为n,里面存了n个数,f(l,r,k)为A[l,r]这个区间里第k大数,
当r-l+1<k时,f(l,r,k)=0.现在计算 nl=1nr=lf(l,r,k)的值

分析:我们只要求出对于一个数xx左边最近的kk个比他大的和右边最近kk个比他大的,扫一下就可以知道有几个区间的kk大值是xx.代码中最后一个for循环比较难理解,要仔细揣摩揣摩。在这里简单的举个例子,理解理解。



#include<stdio.h>#include<iostream>using namespace std;#define LL long long#define max1 500000+5int s[max1],l[max1],r[max1];int main(){    int T;    int n,k;    scanf("%d",&T);    while(T--)    {        scanf("%d %d",&n,&k);        for(int i=0;i<n;i++)        {            scanf("%d",&s[i]);        }        LL ans=0;        for(int i=0;i<n;i++)        {            int right=1,left=1,j;            for(j=i+1;j<n;j++)            {                if(right>k)                    break;                if(s[j]>s[i])                    r[right++]=j-i;//在s[i]右边第right个比s[i]大的数与s[i]的距离为j-i            }            if(j==n)//如果没有找完k个比是s[i]大的数,就把末尾到s[i]的距离算出来                r[right]=n-i;            for(j=i-1;j>=0;j--)            {                if(left>k)                    break;                if(s[j]>s[i])                    l[left++]=i-j;            }//同上            if(j<0)//同上                l[left]=i+1;            for(j=0;j<left;j++)            {                if(k-j-1>=right)                    continue;                int lm=l[j+1]-l[j];                int rm=r[k-j]-r[k-j-1];                ans+=(LL)s[i]*lm*rm;            }        }        printf("%lld\n",ans);    }    return 0;}


 

原创粉丝点击