题目链接

传送门

题解

看完题目后可以立刻想到:先算出最大值, 然后把最大值剔除掉,再找此时的最大值也就是次大值。这样重复\(k\)边即可找到第\(k\)大值。

于是我们只需要考虑找最大值了

我们可以维护后缀和中的最大值(这里的和是指题目中的不统计重复数字的求和)

具体来说, 我们可以建\(n\)课线段树, 第\(i\)颗存的是以\(i\)为结尾的所有后缀和, 那么, 我们可以把每颗线段树的最大值全部扔进一个大根堆, 这样我们就能每次得到当前的最大值。

接着, 我们从堆中取出当前最大值, 设这个最大值是在第\(i\)棵树的\([l, r]\)区间内取得的, 位置为\(p\), 那么我们分别在第\(i\)棵树的\([l, p)\)和\((p, r]\)两区间内找最大值, 然后把它们放入堆中。

显然, 我们可以用主席树优化空间\((\)pushdown一定要记得复制节点!!!!!\()\)

注意: 由于不统计重复数字, 那么在建主席树时, 设当前数字\(a_i\)上次出现位置为\(l\), 那么它的贡献区间为\((p, i)\)

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm> #include <vector>
#include <queue>
#include <map> using namespace std; typedef long long LL; #define fi first
#define se second
typedef pair <LL, int> pr; const LL INF = 1e14; const int N = 100010; int root[N]; struct SegmentTree
{
int ls[N * 400], rs[N * 400], sz;
LL addv[N * 400];
pr maxv[N * 400]; int cpyNode(int x)
{
int cur = ++sz;
ls[cur] = ls[x];
rs[cur] = rs[x];
maxv[cur] = maxv[x];
addv[cur] = addv[x];
return cur;
} inline int downtag(int x, LL v)
{
int cur = cpyNode(x);
addv[cur] += v;
maxv[cur].fi += v;
return cur;
} inline void pushdown(int cur)
{
if (addv[cur])
{
if (ls[cur]) ls[cur] = downtag(ls[cur], addv[cur]);
if (rs[cur]) rs[cur] = downtag(rs[cur], addv[cur]);
addv[cur] = 0;
}
} void build(int & cur, int l, int r)
{
cur = ++sz;
addv[cur] = 0;
if (l == r) { maxv[cur] = make_pair(0, -l); return; }
int mid = (l + r) >> 1;
build(ls[cur], l, mid);
build(rs[cur], mid+1, r);
maxv[cur] = max(maxv[ls[cur]], maxv[rs[cur]]);
} void update(int & cur, int pre, int l, int r, int ql, int qr, LL v)
{
if (ql == l && qr == r)
cur = downtag(pre, v);
else
{
pushdown(pre);
cur = cpyNode(pre);
int mid = (l + r) >> 1;
if (qr <= mid)
update(ls[cur], ls[pre], l, mid, ql, qr, v);
else if (ql > mid)
update(rs[cur], rs[pre], mid+1, r, ql, qr, v);
else
update(ls[cur], ls[pre], l, mid, ql, mid, v),
update(rs[cur], rs[pre], mid+1, r, mid+1, qr, v);
maxv[cur] = max(maxv[ls[cur]], maxv[rs[cur]]);
}
} pr query(int cur, int l, int r, int ql, int qr)
{
if (ql == l && qr == r)
return maxv[cur];
pushdown(cur);
int mid = (l + r) >> 1;
if (qr <= mid)
return query(ls[cur], l, mid, ql, qr);
else if (ql > mid)
return query(rs[cur], mid+1, r, ql, qr);
else
return max(query(ls[cur], l, mid, ql, mid),
query(rs[cur], mid+1, r, mid+1, qr));
}
} seg; int n, k; LL a[N]; int last[N];
map <LL, int> pos; struct Data
{
int id, pl, pr, pos; LL val;
Data() { }
Data(int _1, int _2, int _3, int _4, LL _5) : id(_1), pl(_2), pr(_3), pos(_4), val(_5) { }
bool operator < (const Data & rhs) const { return val < rhs.val; }
}; priority_queue <Data> q; int main()
{
scanf("%d %d", &n, &k); for (int i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
last[i] = pos[a[i]];
pos[a[i]] = i;
} seg.build(root[0], 1, n);
for (int i = 1; i <= n; i++)
seg.update(root[i], root[i-1], 1, n, last[i]+1, i, a[i]); for (int i = 1; i <= n; i++)
{
pr res = seg.query(root[i], 1, n, 1, i);
q.push(Data(i, 1, i, -res.se, res.fi));
}
Data res;
for (int i = 1; i <= k; i++)
{
res = q.top(); q.pop();
if (res.pl < res.pos)
{
pr now = seg.query(root[res.id], 1, n, res.pl, res.pos-1);
q.push(Data(res.id, res.pl, res.pos-1, -now.se, now.fi));
}
if (res.pr > res.pos)
{
pr now = seg.query(root[res.id], 1, n, res.pos+1, res.pr);
q.push(Data(res.id, res.pos+1, res.pr, -now.se, now.fi));
}
}
printf("%lld\n", res.val); return 0;
}

最新文章

  1. C# 二维数组相关知识记录
  2. Python中出现的异常
  3. service(启动方式)
  4. UVA 10816 + HDU 1839 Dijstra + 二分 (待研究)
  5. shell配置环境变量
  6. OpenJudge/Poj 2027 No Brainer
  7. bzoj 2402: 陶陶的难题II 二分答案维护凸包
  8. 第六篇:R语言数据可视化之数据分布图(直方图、密度曲线、箱线图、等高线、2D密度图)
  9. 2015第19周四jquery版本
  10. VS 2013--工程的创建,scanf报错,常用快捷键,行号设置
  11. Java NIO的性能
  12. webpack-dev-server运行时报错
  13. NullReferenceException 的可恨之处
  14. linux c++ curl https 请求并双向验证SSL证书
  15. APIView流程——请求方式分发
  16. PHP 4种输出的方式
  17. sp_settriggerorder 设置触发器执行顺序
  18. 利用IDA6.6进行apk dex代码动态调试
  19. Scrollbar中滚动条的设置
  20. Sass、Less编译器koala及koala不支持中文字体的解决方法

热门文章

  1. Fabric基础架构原理(一)
  2. iOS即时通讯之CocoaAsyncSocket源码解析五
  3. linux管理权限
  4. ConcurrentSkipListMap 源码分析
  5. CentOS7设置启动模式问题
  6. log4j.rootLogger作用域
  7. 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第1节 Scanner类_1-API概述和使用步骤
  8. 操作Redis--hash/key-value
  9. window10 本地搭建SVN服务器
  10. js提交图片转换为base64