题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006

每个右端点的左端点在一个区间内;用堆记录端点位置、可选区间,按价值排序;拿出一个后也许分裂成两个。

第一次写了ST表,写得巨复杂,记录向前/后的最小值和位置,还为了预处理,又记 2^j 走到哪;调了半天边界,最后发现是Lg写错了!至今仍不知那样写为什么会错……

看看别人的代码,原来不用记两个方向的,用的时候往前跳几步再用向后的就行!也不用记录最小值,只要记录位置就行了;也不用记录 to[ ][ ] ,只要从 i+2^j 有没有超过n就能判断边界。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int N=5e5+,Lm=;
int n,m,L,R,a[N],s[N],Lg[N],stp[N][Lm+],stn[N][Lm+],to[N][Lm+];
int idp[N][Lm+],idn[N][Lm+];
ll ans;
struct Node{
int ps,to,l,r,v;
Node(int p,int t,int l,int r,int v):ps(p),to(t),l(l),r(r),v(v) {}
bool operator< (const Node &b) const
{return v<b.v;}
};
priority_queue<Node> q;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='') ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return fx?ret:-ret;
}
void init()
{
/*
int i=1,cd=0,nxt;
for(;i<=n;i=nxt,cd++)
{
nxt=i<<1;
for(int j=i;j<nxt&&j<=n;j++) Lg[j]=cd;
}
i>>=1;
for(;i<=n;i++) Lg[i]=cd;
*/
for(int i=;i<=n;i++) Lg[i]=Lg[i>>]+; memset(to,0x3f,sizeof to);//
for(int i=;i<n;i++)
{
stp[i][]=s[i]; idp[i][]=i;
to[i][]=i-;
for(int j=,d;j<=Lm;j++)
{
d=to[i][j-];
if(d<||to[d][j-]>n)break;// >n!!! //if d<0
to[i][j]=to[d][j-];
if(stp[d][j-]<stp[i][j-])
{
stp[i][j]=stp[d][j-]; idp[i][j]=idp[d][j-];
}
else
{
stp[i][j]=stp[i][j-]; idp[i][j]=idp[i][j-];
}
}
}
memset(to,0x3f,sizeof to);
for(int i=n-;i>=;i--)
{
stn[i][]=s[i]; idn[i][]=i;
to[i][]=i+;
for(int j=,d;j<=Lm;j++)
{
d=to[i][j-];
if(to[d][j-]>n)break;
to[i][j]=to[d][j-];
if(stn[d][j-]<stn[i][j-])
{
stn[i][j]=stn[d][j-]; idn[i][j]=idn[d][j-];
}
else
{
stn[i][j]=stn[i][j-]; idn[i][j]=idn[i][j-];
}
}
}
}
int main()
{
n=rdn(); m=rdn(); L=rdn(); R=rdn();
for(int i=;i<=n;i++) a[i]=rdn(),s[i]=s[i-]+a[i];
init();
for(int i=,d,t;i<=n;i++)
{
int l=i-R,r=i-L;//not +1
if(r<) continue; l=max(l,);
t=Lg[r-l+];//not +1
d=(stp[r][t]<stn[l][t]?idp[r][t]:idn[l][t]);
q.push(Node(i,d,l,r,s[i]-s[d]));
} while(m--)
{
Node k=q.top(); q.pop(); ans+=k.v;
int l1=k.l,r1=k.to-, l2=k.to+,r2=k.r;
int t,d;
if(l1<=r1)
{
t=Lg[r1-l1+];
d=(stp[r1][t]<stn[l1][t]?idp[r1][t]:idn[l1][t]);
q.push(Node(k.ps,d,l1,r1,s[k.ps]-s[d]));
} if(l2<=r2)
{
t=Lg[r2-l2+];
d=(stp[r2][t]<stn[l2][t]?idp[r2][t]:idn[l2][t]);
q.push(Node(k.ps,d,l2,r2,s[k.ps]-s[d]));
}
}
printf("%lld\n",ans);
return ;
}

bzoj 2006 [NOI2010]超级钢琴——ST表+堆的更多相关文章

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

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

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

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

  3. [BZOJ2006][NOI2010]超级钢琴(ST表+堆)

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 3679  Solved: 1828[Submit][Statu ...

  4. 【BZOJ2006】[NOI2010]超级钢琴 ST表+堆

    [BZOJ2006][NOI2010]超级钢琴 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以 ...

  5. BZOJ 2006 NOI2010 超级钢琴 划分树+堆

    题目大意:给定一个序列.找到k个长度在[l,r]之间的序列.使得和最大 暴力O(n^2logn),肯定过不去 看到这题的第一眼我OTZ了一下午... 后来研究了非常久别人的题解才弄明确怎么回事...蒟 ...

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

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

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

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

  8. 【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)

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

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

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

随机推荐

  1. SolidEdge 工程图中如何标注尺寸公差

    1 先标注基准框,输入基准符号(A B C之类的)   2 点击特征控制,设置马上要标注的特征和公差(可以保存为模板)   3 直接点击要标注的元素即可   4 没有基准的形位公差标注也一样  

  2. Linux命令行编辑常见的快捷键(有用, 通用)

    本文讲述了Linux命令行编辑常见的快捷键,希望对您有所帮助. Linux命令行编辑快捷键: history 显示命令历史列表 ↑(Ctrl+p) 显示上一条命令 ↓(Ctrl+n) 显示下一条命令 ...

  3. node.js如何读取MySQL数据

    先安装mysql模块. node.js默认安装时,模块文件放在 /usr/local/lib/node_modules 这个目录下,为了便宜管理,模块还是统一安装到这里好. $ cd /usr/loc ...

  4. 【浅墨Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 &amp; 纹理混合

    本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://hpw123.net/a/C__/kongzhitaichengxu/2014/1117/120.html 作者:毛星云 ...

  5. Memory-mapped I/O vs port-mapped I/O

    关于MMIO和PIO,我看到的解释最清楚的文章,原文在这里:Memory-mapped I/O vs port-mapped I/O - 2015 Microprocessors normally u ...

  6. 新一代AJAX API:FETCH

    AJAX半遮半掩的底层API是饱受诟病的一件事情. XMLHttpRequest 并不是专为Ajax而设计的. 虽然各种框架对 XHR 的封装已经足够好用, 但我们可以做得更好.更好用的API是 fe ...

  7. STL_算法_查找算法(find、find_if)

    C++ Primer 学习中. .. 简单记录下我的学习过程 (代码为主) find . find_if /**********************线性查找O(n) find(); find_if ...

  8. hdu5317 RGCDQ 统计

    // hdu5317 RGCDQ // // 题目大意: // // 给定一个闭区间[l,r],定义f(x)是x的不同的质因子的个数 // 比方: 12 = 2 * 2 * 3,是两种.所以f(x) ...

  9. EasyDarwin开源流媒体服务器进行RTSP转发过程中将sdp由文件存储改成内存索引

    -本篇由团队成员Fantasy供稿! 原始版本 在Darwin Streaming Server版本中,推送端DoAnnounce的时候后服务器会根据easydarwin.xml中配置的movies_ ...

  10. c# winform中预防窗体重复打开

      当窗体以非模态形式打开的时候,有可能出现重复打开的情形,利用以下的代码可以预防重复打开! foreach (Form f in Application.OpenForms) { if (f.Nam ...