题目链接

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. C语言语法树

  2. Beta 阶段项目计划

    Beta 阶段项目计划 NewTeam 目标 实现用户数量的目标. 在多个平台发布 完成稳定运行.界面优雅的客户端 充分测试,避免发布后出现bug影响用户使用 及时更新开发文档 合理安排时间,避免和其 ...

  3. TP中CURD操作

    CURD操作 CURD操作也就是模型操作数据表的基本操作.C(Create).U(Update).R(Read).D(Delete)操作就是增删改查操作. 6.1.增加操作 回想一下在mysql中增加 ...

  4. day4 列表 增删改查 元组

    增lis=["a","b","c",5,7,4]lis.append("s")#在列表的末尾追加lis.extend(& ...

  5. 洛谷 [USACO09OPEN]工作调度

    题面 读完题,我们会发现有一个很重要的信息,每件物品代价相同,但价值不同.那么我们很容易想到,在满足限制的情况下,我们肯定会选择价值尽可能大的物品. 我们可否用背包来实现呢,答案是否定的,或者说我不会 ...

  6. Redis存储系统

    一.QuickStart 1.Redis简介: redis是一个性能非常优秀的内存数据库,通过key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string ...

  7. 【BZOJ3894】文理分科(最小割)

    [BZOJ3894]文理分科(最小割) 题面 BZOJ Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个 ...

  8. Hbase(六) hbase Java API

    一. 几个主要 Hbase API 类和数据模型之间的对应关系: 1. HBaseAdmin关系: org.apache.hadoop.hbase.client.HBaseAdmin作用:提供了一个接 ...

  9. poj1850 Code

    Code Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 10059   Accepted: 4816 Description ...

  10. 洛谷P3048 [USACO12FEB]牛的IDCow IDs

    P3048 [USACO12FEB]牛的IDCow IDs 12通过 67提交 题目提供者lin_toto 标签USACO2012 难度普及/提高- 时空限制1s / 128MB 提交  讨论  题解 ...