【BZOJ4504】K个串

Description

兔子们在玩k个串的游戏。首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次)。兔子们想知道,在这个数字序列所有连续的子串中,按照以上方式统计其所有数字之和,第k大的和是多少。

Input

第一行,两个整数n和k,分别表示长度为n的数字序列和想要统计的第k大的和
接下里一行n个数a_i,表示这个数字序列

Output

一行一个整数,表示第k大的和

Sample Input

7 5
3 -2 1 2 2 1 3 -2

Sample Output

4

HINT

1 <= n <= 100000, 1 <= k <= 200000, 0 <= |a_i| <= 10^9数据保证存在第 k 大的和

题解:沿用超级钢琴的思路。用堆维护五元组(x,a,b,y,val)表示右端点为x,左端点在[a,b]中,最优的左端点是y,且y到x的和是val。然后每次从优先队列中取出val最大的,将其删去,在[a,y)和(y,b]中分别寻找新的y,然后将其扔回到队列中去。

问题是如何找y呢?考虑可持久化线段树。因为每个区间都是某个前缀的后缀,所以如果当前的右端点是x,x的前驱是pre[x],我们只需要在x的线段树中将(pre[x],x]的权值都加上val[x]即可。可以用标记永久化来加速主席树的区间修改。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
using namespace std;
const int maxn=100010;
typedef long long ll;
int n,m,tot;
ll v[maxn];
int rt[maxn],pre[maxn];
map<ll,int> last;
struct node
{int l,r,x,y;ll v;node() {}node(int a,int b,int c,ll d,int e) {x=a,l=b,r=c,v=d,y=e;}bool operator < (const node &a) const {return v<a.v;}
};
struct sag
{ll x;  int y;sag() {x=-1ll<<60,y=0;}
}s[maxn*100];
int ls[maxn*100],rs[maxn*100];
ll tag[maxn*100];
priority_queue<node> q;
sag operator + (const sag &a,const sag &b)
{return ((a.x==b.x)?(a.y>b.y):(a.x>b.x))?a:b;
}
void build(int l,int r,int &x)
{x=++tot,s[x].x=0,s[x].y=l;if(l==r)  return ;int mid=(l+r)>>1;build(l,mid,ls[x]),build(mid+1,r,rs[x]);
}
void insert(int x,int &y,int l,int r,int a,int b,ll c)
{y=++tot,s[y]=s[x],ls[y]=ls[x],rs[y]=rs[x],tag[y]=tag[x];if(a<=l&&r<=b){s[y].x+=c,tag[y]+=c;return ;}int mid=(l+r)>>1;if(a<=mid) insert(ls[x],ls[y],l,mid,a,b,c);if(b>mid)    insert(rs[x],rs[y],mid+1,r,a,b,c);s[y]=s[ls[y]]+s[rs[y]];s[y].x+=tag[y];
}
sag query(int l,int r,int x,int a,int b)
{if(a<=l&&r<=b) return s[x];int mid=(l+r)>>1;sag ret;ret.y=l;if(a<=mid)    ret=ret+query(l,mid,ls[x],a,b);if(b>mid)   ret=ret+query(mid+1,r,rs[x],a,b);ret.x+=tag[x];return ret;
}
inline int rd()
{int ret=0,f=1;   char gc=getchar();while(gc<'0'||gc>'9')  {if(gc=='-')    f=-f;  gc=getchar();}while(gc>='0'&&gc<='9')  ret=ret*10+gc-'0',gc=getchar();return ret*f;
}
int main()
{n=rd(),m=rd();int i,a,b,x;ll y;sag t;node u;build(1,n,rt[0]);for(i=1;i<=n;i++){v[i]=rd(),pre[i]=last[v[i]],last[v[i]]=i;insert(rt[i-1],rt[i],1,n,pre[i]+1,i,v[i]);t=query(1,n,rt[i],1,i);q.push(node(i,1,i,t.x,t.y));}while(m--){u=q.top(),q.pop();x=u.x,a=u.l,b=u.r,y=u.y;if(!m){printf("%lld\n",u.v);return 0;}if(a<y){t=query(1,n,rt[x],a,y-1);q.push(node(x,a,y-1,t.x,t.y));}if(b>y){t=query(1,n,rt[x],y+1,b);q.push(node(x,y+1,b,t.x,t.y));}}return 0;
}//8 5 3 -2 1 2 2 1 3 -2

转载于:https://www.cnblogs.com/CQzhangyu/p/7672429.html

【BZOJ4504】K个串 可持久化线段树+堆相关推荐

  1. SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)

    题意: 求树上A,B两点路径上第K小的数 分析: 同样是可持久化线段树,只是这一次我们用它来维护树上的信息. 我们之前已经知道,可持久化线段树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表 ...

  2. 美味佳肴【可持久化线段树】【“纽劢科技杯”第十六届同济大学程序设计竞赛暨上海邀请赛.K题】

    题目链接 题目描述 众所周知,天才程序员菜哭武是一个伟大的厨师.这天,张老师和石头来到菜哭武家做客,想尝一尝菜哭武的手艺. 菜哭武手上有n种食材,每种食材个数无限多,编号为i的食材有一个美味度ai.一 ...

  3. 【NOI2018】你的名字【后缀自动机】【可持久化线段树合并】【乱搞】

    题意:给一个串 SSS,qqq 次询问,每次给定串 TTT 和 l,rl,rl,r ,求有多少个本质不同的串是 TTT 的子串而不是 Sl-rS_{l\dots r}Sl-r​ 的子串. ∣S∣≤5× ...

  4. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

  5. SP10628 COT - Count on a tree (树剖+可持久化线段树)

    题意: 给定一个包含 N 个结点的树. 树节点从 1 到 N编号..每个节点有一个整数权值. 我们会要求您执行以下操作: u v k : 询问从节点 u 到 节点 v 的路径上的第k小的权值 输入 在 ...

  6. 解题报告:P3834 【模板】可持久化线段树 2(主席树)详解

    P3834 [模板]可持久化线段树 2(主席树) 题解 P3834 [[模板]可持久化线段树 2(主席树)] 1)静态求第k大数 可持久化线段树,不能用堆的方法存子结点了,所以用指针l表示左儿子r表示 ...

  7. 可持久化线段树——主席树

    前言: 最近心(po)血(yu)来(ya)潮(li)学习了一下主席树.(再不学就落伍了) 主席树,即可持久化线段树,支持维护和查询区间的第\(k\)大(小).区间不同种类个数等,基于线段树的思想之上 ...

  8. 【模板】可持久化线段树 1(主席树)

    题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...

  9. 洛谷P3919可持久化线段树

    P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目提供者HansBug 站长团 评测方式云端评测 标签O2优化高性能 难度提高+/省选- 时空限制3000ms / 512MB 有了可持久 ...

最新文章

  1. 关于preg_match() / preg_replace()函数的一点小说明
  2. win7系统, vim的_vimrc文件无法修改
  3. php for循环in的用法,JavaScript中for in循环是如何使用的?需要注意些什么?
  4. [转] 前端异常监控解决方案研究
  5. linux系统如何启用ftp服务
  6. mysql xa 演示_mysql的XA事务恢复过程详解
  7. 前端学习(2275)初始化react
  8. c语言定义5个元素数组, 对数组进行从小到大排序,定义一个5行5列的二维数组,并动态赋值,将第3列的数组进行从小到大的排序...
  9. 架构整洁之道 pdf_代码有整洁之道,而架构同样有整洁之道
  10. 新版DevEco不用USB线下载程序
  11. 30hibernate_fetch_1_select
  12. scala中的基础语法
  13. HSRP冗余热备份协议
  14. 合并两个有序数组 Go语言
  15. SQL SERVER 2000 自动下载木马病毒 cmd.exe和ftp.exe解决办法
  16. CODESYS在工厂自动化的应用案例:图尔克RFID射频识别技术的应用
  17. 磁盘显示数据错误循环冗余检查资料怎么寻回
  18. Android面试总结-中高级
  19. 计算机专业知识面狭窄,软件学院“计算机基础”实验教学改革探索
  20. Outlook邮件撤回有时间限制吗_怎么操作?

热门文章

  1. jenkins 手动执行_Jenkins环境配置篇-节点增加
  2. tcp socket编程 java_JAVA TCP Socket编程 计算题
  3. Linux安装和卸载JDK
  4. 笔记(3)——Clustering the tagged web
  5. 46、练习:输出指定目录下的所有文件名称
  6. 记在k8s的pod上使用apache的commons-net:ftp功能时,ftp一直上传文件失败
  7. Notepad++ 64位 Jsonviewer Compareplugin 安装
  8. 删除数组中的指定元素 | JavaScript
  9. Nginx+Tomcat部署Angular+javaweb项目(解决刷新404)
  10. 《c++语言导学》——1.3 Hello,World!