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 r−l+1<k .
Give you k , you need to calculate ∑nl=1∑nr=lf(l,r,k)
There are T test cases.
1≤T≤10
k≤min(n,80)
A[1..n] is a permutation of [1..n]
∑n≤5∗105
Let f(l,r,k) be the k-th largest element of A[l..r] .
Specially , f(l,r,k)=0 if r−l+1<k .
Give you k , you need to calculate ∑nl=1∑nr=lf(l,r,k)
There are T test cases.
1≤T≤10
k≤min(n,80)
A[1..n] is a permutation of [1..n]
∑n≤5∗105
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]
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
题意:
给出一个1-n的排列,求所有区间(区间内第k大的数)的和。
思路:
可以转换成对每一个数,求它的统计次数*它的值。对每个数枚举左右两边比它大的数(枚举k个就行,k最大为80)。然后计算一下。
//
// main.cpp
// 1003
//
// Created by zc on 2017/8/7.
// Copyright © 2017年 zc. All rights reserved.
//
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
const int N=550000;
int a[N],l[N],r[N];
int main(int argc, const char * argv[]) {
int T,n,k;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
ll ans=0;
for(int i=1;i<=n;i++)
{
if(n-a[i]+1<k) continue;
int ln=0,rn=0,le=i-1,re=i+1;
l[0]=r[0]=i;
while(le>0&&ln<k)
{
if(a[le]>a[i]) l[++ln]=le;
le--;
}
l[++ln]=0;
while(re<=n&&rn<k)
{
if(a[re]>a[i]) r[++rn]=re;
re++;
}
r[++rn]=n+1;//cout<<i<<" "<<ln<<" "<<rn<<endl;
for(int j=k-1;j>=0;j--)
{
if(j<ln&&k-j-1<rn) ans+=(ll)(l[j]-l[j+1])*(r[k-j]-r[k-j-1])*a[i];//cout<<i<<" "<<j<<" "<<ans<<endl;
if(k-j-1>rn) break;
}
}
printf("%lld\n",ans);
}
}