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. P2127 序列排序

    题目描述 小C有一个N个数的整数序列,这个序列的中的数两两不同.小C每次可以交换序列中的任意两个数,代价为这两个数之和.小C希望将整个序列升序排序,问小C需要的最小代价是多少? 输入输出格式 输入格式 ...

  2. 【转】The test form is only available for requests from the local machine 解决方法

    描述:在内网可以访问 WebServer     ,在外部网站无法通过IP调用 webserver 转自:http://www.cnblogs.com/xiaogelove/p/3447283.htm ...

  3. [NOIP2002] 字串变换 宽搜+深度优化

    这道题硬是让我用STL水过.......而且题解里说的什么双向宽搜,交替扩展............... 这道题反正,STL用就用吧,但是状态数可以卡到千亿级别,因为这个东西是阶乘扩展的,然后我们发 ...

  4. Xamarin+vs2010部署错误:error MSB6004: 指定的任务可执行文件位置\sdk\\tools\zipalign.exe”无效

    好不容易配好了Xamarin和vs2010,也搞好了GenyMotion的虚拟机配置,开始调试的时候又报出了这样的错误: error MSB6004: 指定的任务可执行文件位置"C:\Use ...

  5. Spring任务调度<task:scheduled-tasks>【含cron参数详解】 (转载)

    Spring内部有一个task是Spring自带的一个设定时间自动任务调度 task使用的时候很方便,但是他能做的东西不如quartz那么的多! 可以使用注解和配置两种方式,配置的方式如下 引入Spr ...

  6. Activiti工作流引擎核心介绍

    引言 Activiti 作为一个遵从 Apache 许可的工作流和业务流程管理开源平台,其核心是基于 Java 的超快速.超稳定的 BPMN 2.0 流程引擎,强调流程服务的可嵌入性和可扩展性,同时更 ...

  7. 使用state模块部署lamp架构

    install_httpd: pkg.installed: - name: httpd httpd_running: service.running: - name: httpd - enable: ...

  8. bzoj1575 [Usaco2009 Jan]气象牛Baric

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1575 [题解] 动态规划,令f[i,j]表示前i个选了j个,且第i个必选的最小值. 转移就枚 ...

  9. bzoj 1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居——排序+贪心+set

    Description 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”.每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi(l ...

  10. [BZOJ1391]解题报告|网络流的又一类建图&Dinic的若干优化

    1391: [Ceoi2008]order 有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成. 现在给出这些参数, ...