17 多校 3 - 1003 - Kanade's sum (HDU 6058)
2017-08-03 17:33
465 查看
Kanade's sum
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2286 Accepted Submission(s): 943
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
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
题意:求所有区间中第k大的数之和
可以转化为求一个数 x 为第k大的区间有多少个,设为F(x)个 ,可得答案为∑F(x)*x。
把所有数按输入顺序用链表连接后,从小到大遍历所有的数,求出各自的F(x)值,每求一个删一个数使得链表中的数总是 ≥ x ,求F(x)的方法都差不多,都是比较暴力的方法直接来,从数 x 的位置开始往前找,找 k-1 个比 x 大的数记录左位置L,如果没有k-1个就再往后找记录右位置R,直到 [L,R] 区间内只有 k-1 个比 x 大的数,同时还要两边再往外拓展出去,向左下一个比 x 大的数位置和L位置之间的距离就是可以拓展出去的记为A,右边同理记为B,可得以这一区间内的k-1个比x大的数字可以组成A*B个区间,然后再将最左边的大于x的数去掉,最右边再加入一个,再进行上述操作,最后求和就得到了F(x)。
#include<iostream> #include<string.h> #include<stdio.h> using namespace std; const int N = 500000+100; int t,n,k,pos ;//pos 用来记录各个位置所对应的值 struct node { int pos,pre,next;//分别代表每个值所对应的位置、上一个点所对应的位置、下一个点所对应的位置 }a ; void del(int x)//删除操作 { int pre,nxt; pre = a[x].pre; nxt = a[x].next; if(pre==-1||nxt==-1) { if(pre==-1&&nxt==-1) return; else if(pre==-1) { nxt = pos[nxt]; a[nxt].pre = -1; } else { pre = pos[pre]; a[pre].next = -1; } } else { pre = pos[pre]; nxt = pos[nxt]; a[pre].next = a[nxt].pos; a[nxt].pre = a[pre].pos; } } long long f(int x) { int l,r,cnt=0; l = r = a[x].pos; while(1) { if(a[pos[l]].pre==-1||cnt==k-1) break; l = a[pos[l]].pre; cnt++; } while(cnt<k-1) { if(a[pos[r]].next==-1) break; r = a[pos[r]].next; cnt++; } long long ans = 0; while(1) { int A = l - a[pos[l]].pre; int B = a[pos[r]].next==-1?n:a[pos[r]].next;//要注意在该点之后没有比x大的点的情况 B = B - r; ans += A * B; l = a[pos[l]].next; r = a[pos[r]].next; if(l==-1||r==-1||l>a[x].pos) break; } return ans; } int main() { scanf("%d",&t); while(t--) { memset(a,-1,sizeof a); memset(pos,-1,sizeof pos); scanf("%d%d",&n,&k); for(int i=0;i<n;i++) { int num; scanf("%d",&num); pos[i] = num; a[num].pos = i; a[num].pre = i-1; a[num].next = i+1; if(i+1==n) a[num].next = -1; } long long ans = 0; for(int i=1;i<=n-k+1;i++) { ans += f(i)*i; del(i); } printf("%lld\n",ans); } return 0; }
相关文章推荐
- HDU 6058 2017 Multi-University Training Contest - Team 3 1003 :Kanade's sum:简单计数问题
- 2017 Multi-University Training Contest - Team 3 1003(hdu 6058) Kanade's sum(链表)(set)
- 2017多校联合第三场 1003题 hdu 6058 Kanade's sum 链表
- HDU 2017 多校联合训练赛3 3003 6058 Kanade's sum 枚举 模拟链表
- 【多校训练】hdu 6058 Kanade's sum
- HDU-2017 多校训练赛3-1003-Kanade’s sum
- HDU 6058 Kanade's sum(多校3)
- (2017多校训练第三场)HDU - 6058 Kanade's sum 链表
- 2017 多校训练第三场 HDU 6058 Kanade's sum
- hdu 6058 Kanade's sum(思维)
- hdu 6058 Kanade's sum
- hdu 6058 Kanade's sum 维护链表
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum
- 17 多校 - 2 - 1003 - Maximum Sequence (HDU - 6047)
- HDU 6058 枚举 Kanade's sum
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 多校联赛 Kanade's sum
- HDU 6058 Kanade's sum 逆序求第k大
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )