hdu6058

题意

定义 \(f(l, r, k)\) 函数为区间 \([l, r]\) 第 \(k\) 大的数,如果 \(r - l + 1 < k\),\(f = 0\) 。求 \(\sum_{l=1}^{n}\sum_{r=l}^{n}f(l, r, k)\) 。

分析

我们直接去算每个数字在多少个区间为第 \(k\) 大的数,那么一定和它前面和后面的 \(k\) 个大于它的数有关(如果有的话),现在问题就是怎么快速找出它前面和后面大于它的 \(k\) 个数。

对于 \([1, n]\) 每个数,用两个数组分别指向它所在的位置前面的值和后面的值的位置,那么从 \(1\) 到 \(n\) 计算,算完之后删掉(更改它后面的值向前的指向,更改它前面的值向后的指向),这样对于每个数向左向右最多跳 \(k\) 次。复杂度 \(O(k * n)\) 。

code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int MAXN = 5e5 + 10;
int n, k;
int pre[MAXN], nxt[MAXN], pos[MAXN];
int l[MAXN], r[MAXN];
void del(int x) {
pre[nxt[x]] = pre[x];
nxt[pre[x]] = nxt[x];
}
ll cal(int x) {
int c1 = 0, c2 = 0;
for(int i = x; i > 0; i = pre[i]) {
l[++c1] = i - pre[i];
if(c1 == k) break;
}
for(int i = x; i <= n; i = nxt[i]) {
r[++c2] = nxt[i] - i;
if(c2 == k) break;
}
ll res = 0;
for(int i = 1; i <= c1; i++) {
if(k - i + 1 <= c2) {
res += 1LL * l[i] * r[k - i + 1];
}
}
return res;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
pos[x] = i;
pre[i] = i - 1;
nxt[i] = i + 1;
}
pre[0] = 0; nxt[n + 1] = n + 1;
ll ans = 0;
for(int i = 1; i <= n; i++) {
ans += cal(pos[i]) * i;
del(pos[i]);
}
printf("%lld\n", ans);
}
return 0;
}

hdu6058的更多相关文章

  1. hdu6058[链表维护] 2017多校3

    用一个双向链表来查找比当前元素大的前k-1个元素和后k-1个元素 ,从小到大枚举x,算完x的贡献后将x从链表中删除,优化到O(nk). /*hdu6058[链表维护] 2017多效3*/ #inclu ...

  2. hdu-6058 Kanade's sum

    题意:略 思路:要我们求每个区间第K大数之和,其实可以转换为求多少个区间的第K大数是X,然后我们在求和就好了. 那么我们可以从小到大枚举所有可能成为第K大的数.为什么从小到大呢? 因为从小到大我们就略 ...

  3. 【hdu6058】 Kanade's sum 模拟

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6058 题目大意:给你一个$1$到$n$的排列,请求出该序列所有区间中第$k$大之和,若该区间内少于$ ...

  4. 2017 Multi-University Training Contest - Team 3—HDU6058 Kanade's sum

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6058 题目意思:给你一个排列,求所有区间长度大于等于k的区间第k大的数的和…… 思路:一开始看到区间k ...

  5. HDU6058 Kanade's sum(思维 链表)

    Kanade's sum Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  6. 【set】【链表】hdu6058 Kanade's sum

    f(l,r,K)表示区间l,r里面的K大值,问你所有连续子区间的f之和. l(i)表示i左侧第一个比它大的数的位置,r(i)表示i右侧第一个比它大的数的位置.可以用set处理出来. 把数从大到小排序, ...

  7. hdu6058 Kanade's sum 区间第k大

    /** 题目:Kanade's sum 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6058 题意:给定[1,n]的排列,定义f(l,r,k)表示区间[l ...

随机推荐

  1. Android中代码设置RadioButton的高端技巧

    不知道怎么起标题,就这样了. 目前主要讲两个方面内容: 代码方式 设置RadioButton的 android:button . android:background 等属性为 @null : 代码方 ...

  2. Leetcode 45. Jump Game II(贪心)

    45. Jump Game II 题目链接:https://leetcode.com/problems/jump-game-ii/ Description: Given an array of non ...

  3. concurrent

    from concurrent.futures import ThreadPoolExecutor

  4. IEEE 802.15介绍

    1. 无线通信 无线通信主要是利用无线电(Radio)射频(RF)技术的通信方式,无线网络是采用无线通信技术实现的网络无线网络可为两种: 近距离无线网络和远距离无线网络 近距离无线网络主要可分为如下两 ...

  5. 聊聊C++模板函数与非模板函数的重载

    前言 函数重载在C++中是一个很重要的特性.之所以有了它才有了操作符重载.iostream.函数子.函数适配器.智能指针等非常有用的东西. 平常在实际的应用中多半要么是模板函数与模板函数重载,或者是非 ...

  6. 使用lombok省略get、set代码

    首先下载lombok的jar包,如果是maven项目,直接加依赖 <dependency> <groupId>org.projectlombok</groupId> ...

  7. Oracle存储过程学习笔记

    SQL是一种语言! SQL是一种语言! SQL是一种语言! 个人理解:存储过程就相当于Java中的方法;声明变量区域就相当于java中的声明局部变量一样,只是放到一个指定区域定义了 一.先看一部分基础 ...

  8. mysql常用函数示例

    CREATE TABLE `orders` ( `OrderId` INT(10) NOT NULL AUTO_INCREMENT COMMENT '编号', `ProductName` VARCHA ...

  9. jquery发送json请求,给springmvc接收

    js var obj = { 'name':name, 'desc':desc, 'scheduleStartTime':scheduleStartTime, 'scheduleEndTime':sc ...

  10. python memcache操作-安装、连接memcache

    安装memecache wget http://memcached.org/latest tar -zxvf memcached-1.x.x.tar.gz cd memcached-1.x.x ./c ...