题目链接

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

题意:

给你一个n个数的排列,问你全部区间第k大的总和为多少。

分析:

我们只要求出对于一个数x左边最近的k个比他大的和右边最近k个比他大的,扫一下就可以知道有几个区间的k大值是x。

我们考虑从小到大枚举x,每次维护一个链表,链表里只有>=x的数,那么往左往右找只要暴力跳k次,删除也是O(1)的。

时间复杂度:O(nk)

这题只要是知道能从小到大枚举就好办了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const int N=5e5+7;
int t,n,k,a[N],idx[N];///a表示的是这个数组,idx表示的是某个数在的位置
struct Node
{
int pre,nxt,idx;
} node[N]; int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]),idx[a[i]]=i;
node[i]=Node {i-1,i+1,i};
}
node[n+1].idx=n+1;
ll ans=0;
for(int i=1;i<=n;i++)///找到当前这个数
{
int l=idx[i],r=idx[i];///左端点,右端点
int cntl=1,cntr=0;///往前、往后找的数的个数
while(cntl<k)///往前找,看有这个数的前面有多少个数
{
if(node[l].pre==0)break;///左端点已经是第一个元素了
cntl++,l=node[l].pre;
}
while(cntl)///在前面有这么多数的基础上
{
while(cntr+cntl>k)///左右区间的个数大于k了
{
cntr--,r=node[r].pre;///右区间往前移动
}
while(cntl+cntr<k)///左右区间的个数小于k了
{
if(node[r].nxt==n+1)break;///移动到最后也就结束了,不能再往后移动
cntr++,r=node[r].nxt;///右区间往后移动
}
if(cntl+cntr==k)///正好左右区间中有这么多数
{
int L=node[l].idx-node[node[l].pre].idx;///左边涉及的区间
int R=node[node[r].nxt].idx-node[r].idx;///右边涉及的区间
ans+=1ll*L*R*i;
printf("L====%d R====%d i===%d\n",L,R,i);
}
l=node[l].nxt,cntl--;///左区间往后移动
}
node[node[idx[i]].pre].nxt=node[idx[i]].nxt;
node[node[idx[i]].nxt].pre=node[idx[i]].pre;
}
printf("%lld\n",ans);
}
return 0;
}

还有一种纯模拟的方法,比赛的时候我们就是尝试用模拟在写,但是中间的寻找过程没有处理好,时间总是会超,纯模拟的时间控制在O(n^2).下面讲一下具体的解题思路把。

1.我们将当前的a[i]值看作是我们要找的一个区间内的第k大数,获得这个数咋整个数组中的下标。

2.从这个数开始往后找,我们只需要关注比当前这个数大的元素,用一个数组将这些元素保存下来(保存的不是这些数本身,而是它们于我们的第k大值a[i]之间的元素差,即用这个数的小标j减去i)直到找到数组末尾或者说找到了k-1个比a[i]大的数则结束。

3.如果说我们在第二步中找到了k-1个比a[i]大的数,即我们的j在上一步走到了n的位置,那么我们可以虚拟一下第n+1位有一个比a[i]大的元素,也将它加入到第二步里面的数组后面。

4.我们开始从坐标i-1往前找,找的也是比a[i]大的元素,依旧将这些元素与i的下标差保存下来,直到找到最前面或者说找到了k-1个数。这里同第三步一样,如果找到了最前面也就意味着没有找到k-1个元素,虚拟数组0位之间还有一个比a[i] 大的元素,将其保存下来。

5.然后遍历左边的区间,每一次相当于左边能加上一个,右边的区间能减去一个,且保证这之间的元素的个数正好为k个,那么左边区间当前取到的最前面的元素与再前面那个元素之间的元素个数,加上右面区间最后面的那个元素与其后面那个元素的元素个数就是整个区间可以变化的次数。乘上当前的a[i]。

注意,这里说所的最前面的元素是指对于,取得的这k个元素的区间来说的。

#include<iostream>
#include<cstdio>
using namespace std;
#define read(a) scanf("%d",&a)
#define LL long long
const int maxn=500000+10;
int a[maxn];
int l[maxn],r[maxn];
int main()
{
int t;
read(t);
while(t--)
{
int n,k;
read(n);
read(k);
for(int i=0;i<n;i++)
{
read(a[i]);
}
LL ans=0;
for(int i=0;i<n;i++)
{
int lcnt=1,rcnt=1,j;///lcnt代表元素a[i]左边比他大的数有多少个,rcnt同理
for( j=i+1;j<n;j++)
{
if(rcnt>k)
break;
if(a[j]>a[i])
{
r[rcnt++]=j-i;///r[rcnt]代表右边第rcnt个比a[i]大的数距离a[i]的距离,这个是方便计算的,可以等于j,
///但是计算的时候要特殊处理右边只有一个比a[i]大的时候,下方的rnum=1,比较麻烦,
///原来是那样做的,不建议
}
}
if(j>=n)
r[rcnt]=n-i; ///如果a[i]右边比他大的数没超过k个,
///那么我们知道a[i]右边比他大的数只有rcnt-1个,
///我们假设距离a[i]最远的比他大的那个数为righht,
///(程序中没有right这个变量,这里就是为了方便理解)
///这里的r[rcnt]就是为了方便后面统计right右边有多少个比a[i]小的数
for(j=i-1;j>=0;j--)
{
if(lcnt>k)
break;
if(a[j]>a[i])
{
l[lcnt++]=i-j;///同理上面
}
}
if(j<=0)
l[lcnt]=i+1;///同理上面
for(j=0;j<lcnt;j++)
{
if(k-j-1>=rcnt)
continue;
int lnum=l[j+1]-l[j];
int rnum=r[k-j]-r[k-j-1];
ans+=(LL)a[i]*lnum*rnum;
}
}
printf("%lld\n",ans);
}
return 0;
}

2017ACM暑期多校联合训练 - Team 3 1003 HDU 6058 Kanade's sum (模拟)的更多相关文章

  1. 2017ACM暑期多校联合训练 - Team 8 1008 HDU 6140 Hybrid Crystals (模拟)

    题目链接 Problem Description Kyber crystals, also called the living crystal or simply the kyber, and kno ...

  2. 2017ACM暑期多校联合训练 - Team 7 1009 HDU 6128 Inverse of sum (数学计算)

    题目链接 Problem Description There are n nonnegative integers a1-n which are less than p. HazelFan wants ...

  3. 2017ACM暑期多校联合训练 - Team 6 1003 HDU 6098 Inversion (模拟)

    题目链接 Problem Description Give an array A, the index starts from 1. Now we want to know Bi=maxi∤jAj , ...

  4. 2017ACM暑期多校联合训练 - Team 4 1003 HDU 6069 Counting Divisors (区间素数筛选+因子数)

    题目链接 Problem Description In mathematics, the function d(n) denotes the number of divisors of positiv ...

  5. 2017ACM暑期多校联合训练 - Team 1 1003 HDU 6035 Colorful Tree (dfs)

    题目链接 Problem Description There is a tree with n nodes, each of which has a type of color represented ...

  6. 2017ACM暑期多校联合训练 - Team 2 1003 HDU 6047 Maximum Sequence (线段树)

    题目链接 Problem Description Steph is extremely obsessed with "sequence problems" that are usu ...

  7. 2017ACM暑期多校联合训练 - Team 4 1004 HDU 6070 Dirt Ratio (线段树)

    题目链接 Problem Description In ACM/ICPC contest, the ''Dirt Ratio'' of a team is calculated in the foll ...

  8. 2017ACM暑期多校联合训练 - Team 9 1005 HDU 6165 FFF at Valentine (dfs)

    题目链接 Problem Description At Valentine's eve, Shylock and Lucar were enjoying their time as any other ...

  9. 2017ACM暑期多校联合训练 - Team 9 1010 HDU 6170 Two strings (dp)

    题目链接 Problem Description Giving two strings and you should judge if they are matched. The first stri ...

随机推荐

  1. 软工网络15团队作业4-DAY3

    昨天的工作. 张陈东芳:数据库连接的检查 吴敏烽:商品实体类的检查 周汉麟:继续研究获取商品信息方法的方法和调试 林振斌:继续研究获取商品信息方法的方法和调试 李智:Cookies的检查 全体人员:优 ...

  2. JS扫雷原理性代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. yarn add & yarn global add

    yarn global add & add -D https://yarnpkg.com/zh-Hans/docs/cli/add#toc-commands $ yarn global add ...

  4. 第91天:CSS3 属性选择器、伪类选择器和伪元素选择器

    一.属性选择器 其特点是通过属性来选择元素,具体有以下5种形式: 1.E[attr] 表示存在attr属性即可:    div[class] 2.E[attr=val] 表示属性值完全等于val:   ...

  5. POJ3709_K-Anonymous Sequence

     题意很简单,给你若干个数字,你需要减去一些数字,使得在数列中的每个数字出现的次数不少于k次. 一开始我们都会想到是用DP,于是很快我们就可以得出状态为搞定前面i个数所需要花费的最小代价用f[i]表示 ...

  6. ZOJ3084_S-Nim

    题目的意思是这样的,给定你若干堆石子,每次你可以从任一堆取出某些固定数量的石子,每次取完后必须保证没堆石子的数量不为0,谁无法操作了就算fail. 刚刚开始看题目的时候有点也没有思路,甚至连Sg函数也 ...

  7. 【bzoj4027】[HEOI2015]兔子与樱花 树形dp+贪心

    题目描述 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接,我们可以把它 ...

  8. Qt浅谈内存泄露(总结)

    Qt浅谈内存泄露(总结) 来源 http://blog.csdn.net/taiyang1987912/article/details/29271549 一.简介 Qt内存管理机制:Qt 在内部能够维 ...

  9. 【BZOJ4596】黑暗前的幻想乡(矩阵树定理,容斥)

    [BZOJ4596]黑暗前的幻想乡(矩阵树定理,容斥) 题面 BZOJ 有\(n\)个点,要求连出一棵生成树, 指定了一些边可以染成某种颜色,一共\(n-1\)种颜色, 求所有颜色都出现过的生成树方案 ...

  10. sz与rz命令

    一般来说,linux服务器大多是通过ssh客户端来进行远程的登陆和管理的,使用ssh登陆linux主机以后,如何能够快速的和本地机器进行文件的交互呢,也就是上传和下载文件到服务器和本地:   与ssh ...