HDU 6058 Kanade's sum —— 2017 Multi-University Training 3
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6058 Kanade's sum —— 2017 Multi-University Training 3相关的知识,希望对你有一定的参考价值。
Kanade‘s sum
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2512 Accepted Submission(s): 1045
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
题目大意:给定数列A,A是1,2,...,n的一个排序,求数列中所有区间的第k小的数之和。
思路:对于1~n的某个数 i,向左向右分别数出 k 个比 i 大的数,求得第 k 小的数是 i 的最大区间。然后在这个最大区间里,从左往右每次取k个不小于 i 的数,每一次更新区间时加上前后两个区间的差值即可。
AC代码(借鉴了下网上的代码):
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<vector> 5 #include<algorithm> 6 #include<fstream> 7 using namespace std; 8 int a[500005]; 9 long long l[90], r[90]; 10 int main() 11 { 12 int T,n,k; 13 //ifstream cin("ylq.txt"); 14 cin>>T; 15 while(T--) 16 { 17 scanf("%d %d", &n, &k); 18 //cin>>n>>k; 19 for(int i=1;i<=n;i++) scanf("%d", &a[i]); 20 int t; 21 long long ans=0; 22 for(int i=1;i<=n;i++){ 23 t=0; 24 l[t++]=i; 25 int j; 26 for(j=i-1;j>0&&t<k;j--){ 27 if(a[j]>a[i]){ 28 l[t++]=j; 29 } 30 } 31 long long sum=0; 32 if(t==k) 33 { 34 int tmp=1; 35 for(;j>0;j--){ 36 if(a[j]<a[i]) tmp++; 37 else break; 38 } 39 sum+=tmp; 40 for(j=i+1;j<=n&&t>=0;j++){ 41 if(a[j]<a[i]) sum+=tmp; 42 else{ 43 t--; 44 if(t==0) break; 45 tmp=l[t-1]-l[t]; 46 sum+=tmp; 47 } 48 } 49 } 50 else 51 { 52 for(j=i+1;j<=n&&t<k;j++){ 53 if(a[j]>a[i]) l[t++]=j; 54 } 55 if(t==k) 56 { 57 sort(l, l+t); 58 int tmp=l[0]; 59 int p=0; 60 sum+=tmp; 61 for(;j<=n&&p<t;j++){ 62 if(a[j]<a[i]) sum+=tmp; 63 else{ 64 p++; 65 if(l[p]>i) break; 66 tmp=abs(l[p]-l[p-1]); 67 sum+=tmp; 68 } 69 70 } 71 } 72 } 73 ans+=(long long)(sum*a[i]); 74 } 75 cout<<ans<<endl; 76 } 77 }
以上是关于HDU 6058 Kanade's sum —— 2017 Multi-University Training 3的主要内容,如果未能解决你的问题,请参考以下文章
HDU 6058 Kanade's sum —— 2017 Multi-University Training 3
链表2017多校训练3 HDU 6058 Kanade's sum