bzoj 4504: K个串
2016-04-12 11:23
316 查看
求全局第k大,k比较小,不难想到要找到当前最大的数之后去拓展几个小一点的数。
用主席树维护右端点是每个数时左端点的答案,发现加入一个数后更改的是[pre[i],i]连续的一段
开始我自己想,把根节点加入堆中,然后每次加入它的两个儿子节点,如果l==r就是答案,但是这样很难处理答案为负数的情况
实际上,堆中维护的是五元组(root,l,r,id,mx)表示现在的右端点是root,当前代表的区间是l,r,这其中取到的最大值是mx,位置是id。
然后,每次出堆后加入(root,l,id-1,?,?), (root,id+1,r,?,?)
用主席树维护右端点是每个数时左端点的答案,发现加入一个数后更改的是[pre[i],i]连续的一段
开始我自己想,把根节点加入堆中,然后每次加入它的两个儿子节点,如果l==r就是答案,但是这样很难处理答案为负数的情况
实际上,堆中维护的是五元组(root,l,r,id,mx)表示现在的右端点是root,当前代表的区间是l,r,这其中取到的最大值是mx,位置是id。
然后,每次出堆后加入(root,l,id-1,?,?), (root,id+1,r,?,?)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md
#define TR 7000010
using namespace std;
map<int,int> mp;
struct QQ { int rt,l,r,id; ll mx;};
struct cmp
{
bool operator () (QQ a,QQ b) { return a.mx<b.mx;}
};
priority_queue<QQ,vector<QQ>,cmp> q;
struct Tr { ll mx; int id;} tr; int ch[2]; ll ad,mx ; int root[100010];int cnt=0;Tr update(Tr a,Tr b){Tr ans;if (b.mx>a.mx) ans=b;else ans=a;return ans;}void insert(int &i,int pre,int l,int r,int ql,int qr,int d){i=++cnt; ch[i][0]=ch[pre][0]; ch[i][1]=ch[pre][1]; ad[i]=ad[pre];if (ql<=l&&r<=qr) { ad[i]+=d; tr[i].mx=tr[pre].mx+d; tr[i].id=tr[pre].id; return; }int mid=(l+r)>>1;if (ql<=mid) insert(ch[i][0],ch[pre][0],l,mid,ql,qr,d);if (mid+1<=qr) insert(ch[i][1],ch[pre][1],mid+1,r,ql,qr,d);tr[i]=update(tr[ch[i][0]],tr[ch[i][1]]);tr[i].mx+=ad[i];}void build(int &i,int l,int r){i=++cnt; tr[i].id=l;if (l==r) return;int mid=(l+r)>>1;build(ch[i][0],l,mid); build(ch[i][1],mid+1,r);}Tr query(int i,int l,int r,int ql,int qr){if (ql<=l&&r<=qr) return tr[i];int mid=(l+r)>>1; Tr ans;if (qr<=mid) ans=query(ch[i][0],l,mid,ql,qr);else if (mid+1<=ql) ans=query(ch[i][1],mid+1,r,ql,qr);else ans=update(query(ch[i][0],l,mid,ql,qr),query(ch[i][1],mid+1,r,ql,qr));ans.mx+=ad[i];return ans;}int main(){int n,k;scanf("%d%d",&n,&k);build(root[0],1,n);for (int i=1;i<=n;i++){int x;scanf("%d",&x);int pre=mp[x]; mp[x]=i;insert(root[i],root[i-1],1,n,pre+1,i,x);Tr ans=query(root[i],1,n,1,i);q.push((QQ){root[i],1,i,ans.id,ans.mx});}ll ans=0;for (int i=1;i<=k;i++){QQ x=q.top(); q.pop();ans=x.mx;if (x.l<x.id){Tr qu=query(x.rt,1,n,x.l,x.id-1);q.push((QQ){x.rt,x.l,x.id-1,qu.id,qu.mx});}if (x.id<x.r){Tr qu=query(x.rt,1,n,x.id+1,x.r);q.push((QQ){x.rt,x.id+1,x.r,qu.id,qu.mx});}}printf("%lld\n",ans);return 0;}相关文章推荐
- 替换系统流--System.out
- 使用J 4000 enkins配置自动化构建
- Mysql 各种方式安装折腾之一:rpm方式安装
- nslookup通往DNS的桥梁
- GC 面试心得
- Eclipse调试真机时LogCat的显示问题
- MultiDex源码
- Cocos2dx:使用Cocos Studio创建一个简单的工程
- qt中文乱码问题(2)
- [疯狂Java]JDBC:Statement、ResultSet、连接资源自动关闭、Properties配置文件
- LeetCode 之 Increasing Triplet Subsequence
- python list对象
- [转载]登录功能测试总结
- ElasticSearch+Kibana 索引操作( 附源码)
- 对象与json文件之间的转换
- VT5在Win7 64bit上的安装注意事项
- BigDecimal 常用方法
- [翻译中] 树莓派内核编译
- iOS ShareSDK实现分享——微信分享
- 不在mac磁盘上显示的分区