【BZOJ2006】【NOI2010】超级钢琴 Heap+主席树
2014-12-12 17:14
351 查看
题解:
先维护个前缀和sum。然后以i为结束的串就可以有几个j作为开始节点,值sum[i]-sum[j-1]。
我们取最优的j,把sum-sum加到堆里面。
这样就可以O(1)取出最优串值,
取出后,对于这个i,就可以有一个第二优的j为开始的串,我们再把这个串值加入到堆中。
而这个j的优劣因为只跟sum有关,所以不妨写一个主席树寻找静态区间第K大,取得这个j。
这样我们只需要取j次,维护j次,就可以得到最终答案。
数据很良心啊,1A了。。数据范围有代码中注释
代码:
先维护个前缀和sum。然后以i为结束的串就可以有几个j作为开始节点,值sum[i]-sum[j-1]。
我们取最优的j,把sum-sum加到堆里面。
这样就可以O(1)取出最优串值,
取出后,对于这个i,就可以有一个第二优的j为开始的串,我们再把这个串值加入到堆中。
而这个j的优劣因为只跟sum有关,所以不妨写一个主席树寻找静态区间第K大,取得这个j。
这样我们只需要取j次,维护j次,就可以得到最终答案。
数据很良心啊,1A了。。数据范围有代码中注释
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 501000 // N的范围50W,|Ai|<= 1000 #define LOGN 20 #define ls son[x][0] #define rs son[x][1] #define sz size[x] #define inf 0x3f3f3f3f using namespace std; int sum ,crs ,n,m,L,R,rank; long long ans; struct LSH { int x,id; bool operator < (const LSH &a)const{return x<a.x;} }lsh ; struct Heap { int val ,id ,cnt; void pushup(int x){while((x>>1)&&val[x]>val[x>>1])swap(val[x],val[x>>1]),swap(id[x],id[x>>1]),x>>=1;} void pushdown(int x) { int son; while((x<<1)<=cnt) { son=((x<<1|1)<=cnt&&val[x<<1]<val[x<<1|1])?(x<<1|1):(x<<1); if(val[x]<val[son])swap(val[x],val[son]),swap(id[x],id[son]),x=son; else break; } } void push(int w,int note) { ++cnt; val[cnt]=w,id[cnt]=note; pushup(cnt); } int top(){return val[1];} int pop() { int ret=id[1]; val[1]=val[cnt],id[1]=id[cnt]; cnt--; pushdown(1); return ret; } }Heap; struct Functional_Segment_Tree { int son[N*LOGN][2],size[N*LOGN]; int cnt,pos ; void pushup(int x){sz=size[ls]+size[rs];} int build(int last,int l,int r,int d) { int x=++cnt; sz=size[last]; if(l==r){sz++;return x;} int mid=l+r>>1; if(d<=mid)ls=build(son[last][0],l,mid,d),rs=son[last][1]; else rs=build(son[last][1],mid+1,r,d),ls=son[last][0]; pushup(x); return x; } int query(int last,int now,int l,int r,int k) { if(size[now]-size[last]<k)return inf; if(l==r){return l;} int temp=size[son[now][0]]-size[son[last][0]],mid=l+r>>1; if(temp<k)return query(son[last][1],son[now][1],mid+1,r,k-temp); else return query(son[last][0],son[now][0],l,mid,k); } void func() { for(int i=0;i<=n;i++)pos[i+1]=build(pos[i],1,rank,sum[i]); } }fst; int state ; int main() { // freopen("test.in","r",stdin); int i,j,k; int a,b; scanf("%d%d%d%d",&n,&m,&L,&R); for(i=1;i<=n;i++)scanf("%d",&lsh[i+1].x),lsh[i+1].x+=lsh[i].x,lsh[i+1].id=i; sort(lsh+1,lsh+n+2); sum[lsh[1].id]=rank=1,crs[1]=lsh[1].x; for(i=2;i<=n+1;i++) { if(lsh[i].x!=lsh[i-1].x)crs[++rank]=lsh[i].x; sum[lsh[i].id]=rank; } fst.func(); for(i=1;i<=n;i++) { a=max(-1,i-R-1)+1; b=max(-1,i-L)+1; k=fst.query(fst.pos[a],fst.pos[b],1,rank,state[i]=1); if(k<inf)Heap.push(crs[sum[i]]-crs[k],i); } while(m--) { if(!Heap.cnt) { puts("****"); return 0; } ans+=Heap.top(); j=Heap.pop(); a=max(-1,j-R-1)+1; b=max(-1,j-L)+1; k=fst.query(fst.pos[a],fst.pos[b],1,rank,++state[j]); if(k<inf)Heap.push(crs[sum[j]]-crs[k],j); } cout<<ans<<endl; return 0; }
相关文章推荐
- [BZOJ2006][NOI2010][RMQ/主席树][二叉堆]超级钢琴
- [NOI2010][bzoj2006] 超级钢琴 [主席树/ST表+堆]
- BZOJ 2006 NOI 2010 超级钢琴 堆+主席树
- BZOJ 2006 [NOI2010]超级钢琴 主席树+堆
- bzoj2006 [NOI2010]超级钢琴 堆+ST表/主席树
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
- bzoj2006: [NOI2010]超级钢琴(堆+RMQ)
- bzoj 2006: [NOI2010]超级钢琴
- bzoj 2006: [NOI2010]超级钢琴
- bzoj 2006 [NOI2010]超级钢琴 二分答案 可持久化线段树
- bzoj2006 [NOI2010]超级钢琴
- 【BZOJ2006】【NOI2010】超级钢琴(堆)
- [BZOJ2006][NOI2010]超级钢琴-ST表+堆
- BZOJ 2006: [NOI2010]超级钢琴(ST表+优先队列)
- [BZOJ2006][NOI2010]超级钢琴(ST表+堆)
- 2006: [NOI2010]超级钢琴 - BZOJ
- BZOJ2006 [NOI2010]超级钢琴
- BZOJ 2006|NOI 2010|超级钢琴|堆|RMQ
- bzoj 2006: [NOI2010]超级钢琴 可持久化线段树+优先队列
- 【BZOJ】2006: [NOI2010]超级钢琴