[bzoj P4504] K个串
[bzoj P4504] K个串
【题目描述】
兔子们在玩k个串的游戏。首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次)。
兔子们想知道,在这个数字序列所有连续的子串中,按照以上方式统计其所有数字之和,第k大的和是多少。
【输入格式】
第一行,两个整数n和k,分别表示长度为n的数字序列和想要统计的第k大的和
接下里一行n个数a_i,表示这个数字序列
【输出格式】
一行一个整数,表示第k大的和
【样例输入】
7 5
3 -2 1 2 2 1 3 -2
【样例输出】
4
【数据范围】
对于20%的数据,1 <= n <= 2000
对于另外20%的数据,0 <= a_i <= 10^9
对于100%的数据,1 <= n <= 100000, 1 <= k <= 200000, 0 <= |a_i| <= 10^9
数据保证存在第k大的和
题外话:好久都没有用博客园啦,最近写博客都写在WordPress上面。没想到今天炸了。。只好先来cnblogs避一避了。
对于这一题我也是一脸懵逼式的弃疗。连想都没怎么想,丝毫没有办法。
结果——主席树+堆。也是看了题解才明白的。自己怎么也想不到这种方法。
主思路是这样的,维护一个五元组(v,l,r,x,p)表示一个状态,分别表示当前状态所对应区间的和(v),左端点所在区间(l,r),左端点的具体位置(x),右端点的具体位置(p)。(这个思路骑士真的太难想到了,主要一个我觉得,习惯于考虑对称的东西,不会像这样,区间左右端点有别)
先不考虑如何如何构造或得到五元组。假设我们可以很快得到某一个特定的五元组。那如何得出第k大的和?
每一次从堆中取出最大值,也就是当前最大的和,然后做这样的事情:
构造五元组(maxsum_val(),l,p-1,maxsum_pos(),p)和(maxsum_val(),p+1,r,maxsum_pos(),p),并将它们push入堆中。显然这是正确的。
那刚开始在堆里的是什么呢?当然是p=1~n时,左端点在某一点能使区间和最大的这个状态咯。
这个问题——涉及到区间修改,区间查询。肯定要用线段树咯。但是我们发现用线段树是无法处理对于不同的右端点p,查询某个区间最值的问题的。
所以我们对于每一种右端点p,建立一颗主席树,然后在对应的主席树上高即可。
code:
#pragma GCC optimize(2) #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <queue> #define LL long long #define mp make_pair #define pli pair <LL,int> using namespace std; ,M=; int n,m; map <int,int> pre; struct node { LL v; int x,l,r,p; node () {} node (LL _v,int _x,int _l,int _r,int _p) : v(_v),x(_x),l(_l),r(_r),p(_p) {} bool operator < (const node &o) const { return v<o.v; } }; priority_queue <node> q; namespace TREE { int tot,rt[N],lc[M],rc[M]; pli w[M]; LL tag[M]; #define mid (((l)+(r))>>1) #define ms(a,x) memset(a,x,sizeof a) inline ,ms(tag,);} inline void build (int &u,int l,int r) { w[u=++tot]=mp(,l); if (l==r) return; build(lc[u],l,mid),build(rc[u],mid+,r); } inline void insert (int &u,int v,LL z) { tag[u=++tot]=tag[v]+z; lc[u]=lc[v],rc[u]=rc[v],w[u]=w[v],w[u].first+=z; } inline void upload (int u) { w[u]=max(w[lc[u]],w[rc[u]]); } inline void download (int &u) { insert(lc[u],lc[u],tag[u]),insert(rc[u],rc[u],tag[u]); tag[u]=; } inline void modify (int &u,int v,int l,int r,int x,int y,LL z) { if (x<=l&&r<=y) {insert(u,v,z); return;} if (tag[u]) download(v); lc[u=++tot]=lc[v],rc[u]=rc[v],w[u]=w[v]; if (x<=mid) modify(lc[u],lc[v],l,mid,x,y,z); ,r,x,y,z); upload(u); } inline pli query ()) { if (x<=l&&r<=y) return w[u]; if (tag[u]) download(u); if (x<=mid) ret=query(lc[u],l,mid,x,y); ,r,x,y)); return ret; } } using namespace TREE; inline void extend (int x,int l,int r) { if (l>r) return; pli nxt=query(x,,n,l,r); q.push(node(nxt.first,x,l,r,nxt.second)); } int main () { scanf(],,n); ,x; i<=n; ++i) { scanf("%d",&x); modify(rt[i],rt[i-],,n,pre[x]+,i,(LL)x); extend(rt[i],,i),pre[x]=i; } node cur; for ( ; m; --m) { cur=q.top(),q.pop(); extend(cur.x,cur.l,cur.p-); extend(cur.x,cur.p+,cur.r); } printf("%lld\n",cur.v); ; }
[bzoj P4504] K个串的更多相关文章
- bzoj : 4504: K个串 区间修改主席树
4504: K个串 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 268 Solved: 110[Submit][Status][Discuss] ...
- bzoj 4504: K个串 可持久化线段树+堆
题目: Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想 ...
- BZOJ 4504: K个串
题目大意: 求一个序列的第k大的子串和. 题解: 对于一个右端点找最优的左端点,扔进堆里. 每次取堆顶,将这个右端点可以选择的左端点的区间分成两段,扔进堆里,重复k次. 现在需要对于一个固定的右端点, ...
- bzoj 4504: K个串【大根堆+主席树】
像超级钢琴一样把五元组放进大根堆,每次取一个出来拆开,(d,l,r,p,v)表示右端点为d,左端点区间为(l,r),最大区间和值为v左端点在p上 关于怎么快速求区间和,用可持久化线段树维护(主席树?) ...
- bzoj4504 k个串 kstring 可持久化线段树 (标记永久化)
[fjwc2015]k个串 kstring [题目描述] 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只 ...
- 数据结构(主席树):COGS 2213. K个串
2213. K个串 ★★★★ 输入文件:bzoj_4504.in 输出文件:bzoj_4504.out 简单对比时间限制:20 s 内存限制:512 MB [题目描述] 兔子们在玩k个 ...
- BZOJ 3110 K大数查询 | 整体二分
BZOJ 3110 K大数查询 题面 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个 ...
- 问题 K: 周期串plus
问题 K: 周期串plus 时间限制: 1 Sec 内存限制: 128 MB提交: 682 解决: 237[提交] [状态] [命题人:外部导入] 题目描述 如果一个字符串可以由某个长度为k的字符 ...
- hiho#1449 重复旋律6 求长度为k的串最大次数 后缀自动机
题目传送门 题目大意:求长度为k的串的最大次数,把k从1到length的所有答案全部输出. 思路: 这道题放在$SAM$里就是求长度$k$对应的所有$right$集中最大的大小. 我们以$aabab$ ...
随机推荐
- c# 笔记cookie
if (Request.Cookies["svpoint"] != null) { Request.Cookies[].s_SvcID.ToString(); } else { H ...
- IP地址 0.0.0.0 是什么意思?
IP地址0.0.0.0是什么意思? 根据RFC文档描述,它不只是代表本机,0.0.0.0/8可以表示本网络中的所有主机,0.0.0.0/32可以用作本机的源地址,0.0.0.0/8也可表示本网络上的某 ...
- 让网站永久拥有HTTPS - 申请免费SSL证书并自动续期 Let’s Encrypt
让网站永久拥有HTTPS - 申请免费SSL证书并自动续期 Let’s Encrypt 为什么要用HTTPS 网站没有使用HTTPS的时候,浏览器一般会报不安全,而且在别人访问这个网站的时候,很有可 ...
- 牛客OI周赛7-提高组 A 小睿睿的等式
链接:https://ac.nowcoder.com/acm/contest/371/A来源:牛客网 小睿睿在游戏开始时有n根火柴棒,他想知道能摆成形如“A+B=n”的等式且使用的火柴棒数也恰好等于n ...
- 安卓抓包https
https://blog.csdn.net/yichengace/article/details/80167878
- Spark大型电商项目实战-及其改良(3) 分析sparkSQL语句的性能影响
之前的运行数据被清除了,只能再运行一次,对比一下sparkSQL语句的影响 纯SQL的时间 对应时间表 th:first-child,.table-bordered tbody:first-child ...
- hadoop(原生及CDH发行版)关键目录、配置文件及服务对应文件名详解
四个最主要的配置文件(原生版本位于$HADOOP_HOME\etc\hadoop目录):mapred-site.xmlcore-site.xmlhdfs-site.xmlyarn-site.xml 在 ...
- 启动Weblogic问题集锦
报错1:Could not obtain the localhost address. The most likely cause is an error in the network configu ...
- Python模块1
序列化模块: 将原本的字典.列表等内容转换成一个字符串的过程就叫做序列化. 序列化的目的 1.以某种存储形式使自定义对象持久化: 2.将对象从一个地方传递到另一个地方. 3.使程序更具维护性. jso ...
- IIS简单的反向代理设置
下载IIS扩展 1.URL Rewrite 地址: https://www.iis.net/downloads/microsoft/url-rewrite 2.Application Request ...