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 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,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 }

 

 

转载于:https://www.cnblogs.com/MasterSpark/p/7291129.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值