hihocoder#1046: K个串
时间:2019-10-14
本文章向大家介绍hihocoder#1046: K个串,主要包括hihocoder#1046: K个串使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
[传送门]
这种区间内相同数字只能被统计一次/只有区间内数字都不相同才对答案有贡献的题都可以用扫描线扫右端点,表示当前区间右端点为$r$。然后当前线段树/树状数组维护区间左端点为$[1,r)$时对应的答案,那么新加一个数对区间$[last[a[r] + 1, r]$多了$a[r]$的贡献。
这道题也一样。只是因为对于每一个版本的线段树都得用到,所以用了可持久化线段树来维护,第$i$个版本就是右端点为$i$的版本。新加一个数只比上一个版本多了一段区间修改,那么可以用lazy标记来做,注意,这里的lazy可以不下放,因为对答案有贡献的是全局最大值,下传标记没必要(主要也是不会能下传lazy的可持久化线段树。
然后每次都把全局最大值放进优先队列,优先队列里取出最大值,并把该位置删掉,加入该版本下的次大值。重复$K$次即可。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1e5 + 7; const int M = 2e7 + 7; const ll INF = 0x3f3f3f3f3f3f3f3f; struct Node { ll mx; int pos; bool operator < (const Node &rhs) const { return mx < rhs.mx; } }; struct Seg { int lp[M], rp[M]; ll lazy[M]; Node tree[M]; int tol; void update(int &p, int q, int l, int r, int x, int y, ll val) { p = ++tol; if (q) tree[p] = tree[q]; lp[p] = lp[q], rp[p] = rp[q]; lazy[p] = lazy[q]; if (x <= l && y >= r) { lazy[p] += val; tree[p].mx += val; if (l == r) tree[p].pos = l; return; } int mid = l + r >> 1; if (x <= mid) update(lp[p], lp[q], l, mid, x, y, val); if (y > mid) update(rp[p], rp[q], mid + 1, r, x, y, val); tree[p] = max(tree[lp[p]], tree[rp[p]]); tree[p].mx += lazy[p]; } } seg; int root[N]; ll a[N]; priority_queue< pair<Node, int> > que; map<int, int> last; int main() { //printf("%d\n", sizeof(seg) / 1024 / 1024); int n, k; scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); seg.tree[0].mx = -INF; for (int i = 1; i <= n; i++) { seg.update(root[i], root[i - 1], 1, n, i, i, 0); seg.update(root[i], root[i], 1, n, last[a[i]] + 1, i, a[i]); last[a[i]] = i; que.push(pair<Node, int>(seg.tree[root[i]], i)); } ll ans = 0; while (k--) { Node temp = que.top().first; int pos = temp.pos, id = que.top().second; que.pop(); ans = temp.mx; seg.update(root[id], root[id], 1, n, pos, pos, -INF); que.push(pair<Node, int>(seg.tree[root[id]], id)); } printf("%lld\n", ans); return 0; }
原文地址:https://www.cnblogs.com/Mrzdtz220/p/11673228.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- R语言基于协方差的SEM结构方程模型中的拟合指数
- Python贝叶斯回归分析住房负担能力数据集
- 基于R统计软件的三次样条和平滑样条模型数据拟合及预测
- R语言析因设计分析:线性模型中的对比
- R语言逻辑回归、方差分析 、伪R平方分析
- R语言逐步多元回归模型分析长鼻鱼密度影响因素
- R语言对回归模型进行协方差分析
- R语言多项式样条回归、非线性回归数据分析
- R语言中进行Spearman等级相关分析
- R语言相关分析和稳健线性回归分析
- R语言文本挖掘使用tf-idf描述NASA元数据的文字和关键字
- R语言对NASA元数据进行文本挖掘的主题建模分析
- 随机搜索变量选择SSVS估计贝叶斯向量自回归(BVAR)模型
- R语言VAR模型的不同类型的脉冲响应分析
- R语言用向量自回归(VAR)进行经济数据脉冲响应研究分析