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

本来应该是可以用主席树,找区间最小值,取出来后再找那段区间的次小值......

但也可以只找最小值,取出来后把原来区间分裂成两个,继续找最小值,用ST表即可;

发现自己还没写过 ST 表囧...

思路同这里:https://www.cnblogs.com/CQzhangyu/p/7071394.html

自己写了半天,才10分...奋力改了改,那个 find 里面 r++ 而 l 不 ++ 的细节真奇妙...

然后就50分了...

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int const xn=5e5+,inf=0x3f3f3f3f;
int n,k,L,R,t[xn],lg[xn],f[xn][],id[xn][],bin[],ans;
struct N{
int a,b,l,r;
bool operator < (const N &y) const
{return t[b]-t[a]<t[y.b]-t[y.a];}
};
priority_queue<N>q;
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return f?ret:-ret;
}
void find(int l,int r,int &y)
{
int g=lg[r-l+];//
r++;//!!!!!
// printf("id[%d][%d]=%d\n",l,g,id[l][g]);
if(t[id[r][g]]<t[id[l+bin[g]][g]])y=id[r][g];
else y=id[l+bin[g]][g];
// printf("find(%d,%d)=%d\n",l,r,y);
}
int main()
{
n=rd(); k=rd(); L=rd(); R=rd();
bin[]=;
for(int i=,x;i<=n;i++)x=rd(),t[i]=t[i-]+x;
for(int i=,p,lst=;i<=n;i++)
{
if(i<lst*)lg[i]=lg[i-];
else lg[i]=lg[i-]+,lst*=,bin[lg[i]]=lst; id[i][]=i-; f[i][]=i-;
for(int j=;j<=;j++)
{
f[i][j]=f[f[i][j-]][j-];
if(t[id[i][j-]]<t[id[f[i][j-]][j-]])id[i][j]=id[i][j-];
else id[i][j]=id[f[i][j-]][j-];
} int l=max(i-R,),r=i-L,len=r-l+;
if(l>r)continue;
find(l,r,p); q.push((N){p,i,l,r});
// printf("ps:%d,%d\n",p,i);
}
int cnt=,p;
while(cnt<k)
{
int a=q.top().a,b=q.top().b,l=q.top().l,r=q.top().r; q.pop();
if(l<=a-)find(l,a-,p),q.push((N){p,b,l,a-})/*,printf("ps:%d,%d\n",p,b)*/;
if(a+<=r)find(a+,r,p),q.push((N){p,b,a+,r})/*,printf("ps:%d,%d\n",p,b)*/;
cnt++; ans+=t[b]-t[a];
// printf("a=%d b=%d\n",a,b);
}
printf("%d\n",ans);
return ;
}

最后发现把 ans 改成 long long 就A了!!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int const xn=5e5+,inf=0x3f3f3f3f;
int n,k,L,R,t[xn],lg[xn],f[xn][],id[xn][],bin[];
long long ans;
struct N{
int a,b,l,r;
bool operator < (const N &y) const
{return t[b]-t[a]<t[y.b]-t[y.a];}
};
priority_queue<N>q;
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return f?ret:-ret;
}
void find(int l,int r,int &y)
{
int g=lg[r-l+];//
r++;//!!!!!
// printf("id[%d][%d]=%d\n",l,g,id[l][g]);
if(t[id[r][g]]<t[id[l+bin[g]][g]])y=id[r][g];
else y=id[l+bin[g]][g];
// printf("find(%d,%d)=%d\n",l,r,y);
}
int main()
{
n=rd(); k=rd(); L=rd(); R=rd();
bin[]=;
for(int i=,x;i<=n;i++)x=rd(),t[i]=t[i-]+x;
for(int i=,p,lst=;i<=n;i++)
{
if(i<lst*)lg[i]=lg[i-];
else lg[i]=lg[i-]+,lst*=,bin[lg[i]]=lst; id[i][]=i-; f[i][]=i-;
for(int j=;j<=;j++)
{
f[i][j]=f[f[i][j-]][j-];
if(t[id[i][j-]]<t[id[f[i][j-]][j-]])id[i][j]=id[i][j-];
else id[i][j]=id[f[i][j-]][j-];
} int l=max(i-R,),r=i-L,len=r-l+;
if(l>r)continue;
find(l,r,p); q.push((N){p,i,l,r});
// printf("ps:%d,%d\n",p,i);
}
int cnt=,p;
while(cnt<k)
{
int a=q.top().a,b=q.top().b,l=q.top().l,r=q.top().r; q.pop();
if(l<=a-)find(l,a-,p),q.push((N){p,b,l,a-})/*,printf("ps:%d,%d\n",p,b)*/;
if(a+<=r)find(a+,r,p),q.push((N){p,b,a+,r})/*,printf("ps:%d,%d\n",p,b)*/;
cnt++; ans+=t[b]-t[a];
// printf("a=%d b=%d\n",a,b);
}
printf("%lld\n",ans);
return ;
}

A

但已经模仿了TJ啦...处理的时候果然要带上自己,不然各种不方便...

别忘了开 long long !因为是多段区间的和!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int const xn=5e5+,inf=0x3f3f3f3f;
int n,k,L,R,t[xn],lg[xn],id[xn][];
long long ans;
struct N{
int a,b,l,r;
bool operator < (const N &y) const
{return t[b]-t[a]<t[y.b]-t[y.a];}
};
priority_queue<N>q;
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return f?ret:-ret;
}
int mn(int a,int b){return t[a]<t[b]?a:b;}
int find(int l,int r)
{
if(l>r)return -;
int g=lg[r-l+];
return mn(id[l][g],id[r-(<<g)+][g]);
}
int main()
{
n=rd(); k=rd(); L=rd(); R=rd();
for(int i=;i<=n;i++)lg[i]=lg[i>>]+;
for(int i=,x;i<=n;i++)x=rd(),t[i]=t[i-]+x,id[i][]=i;//
for(int j=;(<<j)<=n;j++)
for(int i=;i+(<<j)-<=n;i++)//0 //-1
id[i][j]=mn(id[i][j-],id[i+(<<(j-))][j-]);
for(int i=L;i<=n;i++)q.push((N){find(max(i-R,),i-L),i,max(i-R,),i-L});
int cnt=,p;
while(cnt<k)
{
int a=q.top().a,b=q.top().b,l=q.top().l,r=q.top().r; q.pop();
cnt++; ans+=t[b]-t[a];
int c=find(l,a-),d=find(a+,r);
if(c!=-)q.push((N){c,b,l,a-});
if(d!=-)q.push((N){d,b,a+,r});
}
printf("%lld\n",ans);
return ;
}

bzoj 2006 超级钢琴 —— ST表的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. [BZOJ 2006] 超级钢琴

    Link: https://www.lydsy.com/JudgeOnline/problem.php?id=2006 Algorithm: 对于此类区间最值类问题,我们可以通过控制一端不变来寻找当前 ...

  8. BZOJ 2006 超级钢琴(划分树+优先队列)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2006 题意: 给出一个数列A,L,R,构造出一个新的集合,集合中的数字为A中任意连续t( ...

  9. BZOJ 2006 超级钢琴(堆+主席树)

    很好的一道题. 题意:给出长度为n的数列,选择k个互不相同的区间,满足每个区间长度在[L,R]内,求所有选择的区间和的总和最大是多少.(n,k<=5e5). 首先将区间和转化为前缀和之差,那么我 ...

随机推荐

  1. 『NYIST』第九届河南省ACM竞赛队伍选拔赛[正式赛二]-最小内积(第八届北京师范大学程序设计竞赛决赛)

    H. 最小内积                                                                   Time Limit: 1000ms Memory ...

  2. BZOJ 1022: [SHOI2008]小约翰的游戏John【anti-SG】

    Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取 ...

  3. BZOJ3126: [Usaco2013 Open]Photo

    n<=200000个点,m<=100000个区间,每个区间有且仅有一个点,求最多几个点,无解-1. http://www.cnblogs.com/Chorolop/p/7570191.ht ...

  4. 《TCP/IP详解卷1:协议》——第4章 ARP:地址解析协议(转载)

    章节回顾: 1.引言 当一台主机把以太网数据帧发送到位于同一局域网上的另一台主机时,是根据48 bit的以太网地址来确定目的接口的.设备驱动程序从不检查IP数据报中的目的IP地址.地址解析为这两种不同 ...

  5. POJ 2391 多源多汇拆点最大流 +flody+二分答案

    题意:在一图中,每个点有俩个属性:现在牛的数量和雨棚大小(下雨时能容纳牛的数量),每个点之间有距离, 给出牛(速度一样)在顶点之间移动所需时间,问最少时间内所有牛都能避雨. 模型分析:多源点去多汇点( ...

  6. python之-- socket 基础篇

    socket 网络模块 注意事项:在python3中,所有数据的传输必须用bytes类型(bytes只支持ascii码)所以在发送数据的时候要么在发送的字符串前面加 'b',要么使用encode('u ...

  7. python统一的换行符,实现跨平台

    6 PEP 278: Universal Newline Support The three major operating systems used today are Microsoft Wind ...

  8. volatile关键字解析&内存模型&并发编程中三概念

    原文链接: http://www.cnblogs.com/dolphin0520/p/3920373.html volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java5之前,它是一个 ...

  9. [RxJS] Chain RxJS Operators Together with a Custom `pipe` Function using Array.reduce

    Instead of writing complex operators, it's usually best to write simple, single-purpose operators th ...

  10. react 开发 PC 端项目(一)项目环境搭建 及 处理 IE8 兼容问题

    步骤一:项目环境搭建 首先,你不应该使用 React v15 或更高版本.使用仍然支持 IE8 的 React v0.14 即可. 技术选型: 1.react@0.14 2.bootstrap3 3. ...