HDU 6058-Kanade's sum(多校训练第三场->模拟)

Kanade's sum

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2296    Accepted Submission(s): 947


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
 

Source
 

Recommend

题意:给你n个数,这n个数是一种全排列,问你所有子区间的第k大的数之和。
题解:因为是全排列,从1到n枚举当前第k大的值即可,开两个数组,pre和nxt分别标记当前点往左右延伸的长度就是该点的贡献,之后求波和即可。。
#include<map>            
#include<stack>            
#include<queue>          
#include<vector>            
#include<math.h>      
#include<time.h>    
#include<stdio.h>          
#include<iostream>        
#include<string.h>            
#include<stdlib.h>            
#include<algorithm>            
using namespace std;            
typedef long long  ll;            
#define inf 2147483647           
#define mod 1000000007         
#define maxn  5000005        
#define lowbit(x) (x&-x)            
#define eps 1e-10    
int pre[maxn],nxt[maxn],pos[maxn];
int main(void)
{
	ll sum,ans;
	int n,k,i,j,x,l,r,T;
	scanf("%d",&T);
	while(T--)
	{
		sum=0;
		scanf("%d%d",&n,&k);
		for(i=1;i<=n;i++)
		{
			scanf("%d",&x);
			pos[x]=i;pre[i]=i-1;nxt[i]=i+1;
		}
		pre[0]=0;nxt[n+1]=n+1;
		for(j=1;j<=n;j++)    
		{
			int rc[100];
			r=l=0;x=pos[j];ans=0;
			for(i=x;i<=n && r<k;i=nxt[i])
				rc[++r]=nxt[i]-i;
			for(i=x;i>0 && l<k;i=pre[i])
			{
				l++;
				if(k-l+1>r)
					continue;
				ans+=(i-pre[i])*rc[k-l+1];
			}
			sum+=ans*j;
			pre[nxt[x]]=pre[x];
			nxt[pre[x]]=nxt[x];
		}
		printf("%lld\n",sum);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值