题目大意:给定一个序列。找到k个长度在[l,r]之间的序列。使得和最大

暴力O(n^2logn),肯定过不去

看到这题的第一眼我OTZ了一下午。。。

后来研究了非常久别人的题解才弄明确怎么回事。。。蒟蒻果然不能理解大神的思路啊0.0

首先维护前缀和,那么以第i个元素结尾的和最大的序列自然就是sum[i]-min{sum[j]}(i-r<=j<=i-l)

然后我们维护一个大根堆,每取走一个以i为结尾的元素,增加sum[i]-2thmin{sum[j]}。再取走这个元素就增加sum[i]-3thmin{sum[j]},以此类推

维护区间第k小,划分树。不说啥了吧 尼玛本大爷的划分树竟然还写挂了0.0

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 500500
using namespace std;
typedef pair<int,int> abcd;
typedef long long ll;
int n,k,l,r;ll ans;
int sum[M],a[M],b[M],c[M],s[22][M],now[M];
abcd heap[M];int top;
void insert(abcd x)
{
heap[++top]=x;
int t=top;
while(t>1&&heap[t]>heap[t>>1])
swap(heap[t],heap[t>>1]),t>>=1;
}
void pop()
{
heap[1]=heap[top--];
int t=2;
while(t<=top)
{
if(t<top&&heap[t+1]>heap[t])
t++;
if(heap[t]>heap[t>>1])
swap(heap[t],heap[t>>1]),t<<=1;
else
break;
}
}
void Build_Tree(int l,int r,int dpt)
{
int i,mid=l+r>>1;
int l1=l,l2=mid+1;
int left=mid-l+1;
if(l==r)
return ;
for(i=l;i<=r;i++)
left-=a[i]<c[mid];
for(i=l;i<=r;i++)
{
if(a[i]<c[mid]||a[i]==c[mid]&&left)
b[l1++]=a[i],s[dpt][i]=i==l?1:s[dpt][i-1]+1,left-=a[i]==c[mid];
else
b[l2++]=a[i],s[dpt][i]=i==l? 0:s[dpt][i-1];
}
memcpy(a+l,b+l,r-l+1<<2);
Build_Tree(l,mid,dpt+1);
Build_Tree(mid+1,r,dpt+1);
}
int Get_Ans(int l,int r,int dpt,int x,int y,int k)
{
int mid=l+r>>1;
int l1=x==l? 0:s[dpt][x-1],l2=s[dpt][y];
if(l==r)
return c[mid];
if(k<=l2-l1)
return Get_Ans(l,mid,dpt+1,l+l1,l+l2-1,k);
else
return Get_Ans(mid+1,r,dpt+1,(mid+1)+(x-l-l1),(mid+1)+(y-l+1-l2)-1,k-l2+l1);
}
int main()
{ //freopen("piano.in","r",stdin);
//freopen("piano.out","w",stdout); int i;
cin>>n>>k>>l>>r;
for(i=1;i<=n;i++)
scanf("%d",&sum[i]),sum[i]+=sum[i-1];
memcpy(a,sum,n+1<<2);
memcpy(c,sum,n+1<<2);
sort(c,c+n+1);
Build_Tree(0,n,0);
for(i=l;i<=n;i++)
{
now[i]=1;
int temp=Get_Ans(0,n,0,max(i-r,0),i-l,1);
insert( make_pair(sum[i]-temp,i) );
}
for(i=1;i<=k;i++)
{
abcd temp=heap[1];pop();
if( now[temp.second]!=(temp.second-l)-( max(temp.second-r,0) )+1 )
insert( make_pair(sum[temp.second]-Get_Ans(0,n,0,max(temp.second-r,0),temp.second-l,++now[temp.second]),temp.second) );
ans+=temp.first;
}
cout<<ans<<endl;
}

BZOJ 2006 NOI2010 超级钢琴 划分树+堆的更多相关文章

  1. BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]

    题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...

  2. bzoj 2006 [NOI2010]超级钢琴——ST表+堆

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006 每个右端点的左端点在一个区间内:用堆记录端点位置.可选区间,按价值排序:拿出一个后也许 ...

  3. BZOJ 2006: [NOI2010]超级钢琴 ST表+堆

    开始想到了一个二分+主席树的 $O(n\log^2 n)$ 的做法. 能过,但是太无脑了. 看了一下题解,有一个 ST 表+堆的优美解法. 你发现肯定是选取前 k 大最优. 然后第一次选的话直接选固定 ...

  4. Bzoj 2006: [NOI2010]超级钢琴 堆,ST表

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2222  Solved: 1082[Submit][Statu ...

  5. BZOJ 2006: [NOI2010]超级钢琴( RMQ + 堆 )

    取最大的K个, 用堆和RMQ来加速... ----------------------------------------------------------------- #include<c ...

  6. BZOJ 2006: [NOI2010]超级钢琴

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2613  Solved: 1297[Submit][Statu ...

  7. 洛谷 P2048 BZOJ 2006 [NOI2010]超级钢琴

    题目描述 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中A ...

  8. BZOJ 2006 [NOI2010]超级钢琴 (堆+主席树)

    题面:BZOJ传送门 洛谷传送门 让你求前$K$大的子序列和,$n\leq 5*10^{5}$ 只想到了个$nlog^{2}n$的做法,似乎要被卡常就看题解了.. 好神奇的操作啊,我傻了 我们把序列和 ...

  9. BZOJ.2006.[NOI2010]超级钢琴(贪心 堆)

    BZOJ 洛谷 思路和BZOJ3784一样,用前缀和+堆维护.做那题吧,不赘述啦. (没错我就是水一个AC) //54620kb 1060ms #include <queue> #incl ...

随机推荐

  1. 设计模式之——Factory(工厂模式)

    工厂模式用于,通过统一的创建对象接口来创建对象,而子类可以决定对象的创建方式. class CObject { }; class CCar : public CObject { }; class CF ...

  2. VS2008下OpenCV1.0的设置

    原地址:http://hi.baidu.com/caicai_coco/item/0f3b23e1742e3f11595dd825 1.下载安装最新的OpenCV版本,我使用的是OpenCV_1.0. ...

  3. Selenium: 空指针error

    Error 类型:空指针 可能原因一: 只是引用了该类,但是没有对该类进行实例化(即没有New 一下),即没有给该类分配内存,所以导致空指针: 类调用前注意要实例化,否则会导致空指针错误. 首先声明D ...

  4. WinCE隐藏显示任务栏,当任务栏隐藏时将其显示,当任务栏显示时将其隐藏(FindWindow,ShowWindow,IsWindowVisible),

    HANDLE hWndTaskBar = ::FindWindow(TEXT("HHTaskBar"), NULL);  if(::IsWindowVisible(hWndTask ...

  5. 分享毕业学生“ERP实施project联赛”总结,是肺腑之言——知识是人的价值的体现,每门课程是有意义的学校纪律

    丁.这是我刚刚完成的实习报告,特别是给你一个.阿信,让你知道的真实想法研究生管,我希望你相信在教育管帮助.---雷管1102 刘弈福 以上是刚刚收到(20140427)生邮件,贻富不是我带的毕业设计学 ...

  6. 在gem5的full system下运行 alpha编译的测试程序 running gem5 on ubuntu in full system mode in alpha

    背景 先需要在full system下运行gem5,通过网上查找资料以及向别人请教,终于成功运行,网上大多是关于alpha指令集的,且都是英文的,为了方便大家学习,现在总结一下,希望对大家有所帮助. ...

  7. UNIX高级环境编程1

    UNIX高级环境编程1 故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详. 首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表 ...

  8. 将svnkit转成dlls时的问题

    未处理 System.TypeInitializationException Message="“org.tmatesoft.svn.core.internal.wc.DefaultSVNO ...

  9. openstack学习笔记一 虚拟机启动过程代码跟踪

    openstack学习笔记一 虚拟机启动过程代码跟踪 本文主要通过对虚拟机创建过程的代码跟踪.观察虚拟机启动任务状态的变化,来透彻理解openstack各组件之间的作用过程. 当从horizon界面发 ...

  10. linux网络编程学习笔记之三 -----多进程并发服务端

    首先是fork()函数.移步APUE 8.3.  比較清晰的解释能够參考http://blog.csdn.net/lingdxuyan/article/details/4993883和http://w ...