BZOJ2006: [NOI2010]超级钢琴

4 篇文章 0 订阅

求和为前k大的长为L~R的区间的和

将区间和转前缀和 Ri=Lai=s[R]s[L1]
右端点相同的区间放一起,以他们的区间和的最大值为代表值,把这些右端点放进一个堆里,取k次,每次取区间和最大的右端点出来,将它的左端点区间以最小的s[L-1]的L为界,取出这个L,剩下的分成两部分,求出这两部分s[L-1]的最小值,算出各自最大的区间和,把他们放进堆里

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

inline void swap(int &x,int &y){x^=y;y^=x;x^=y;}
inline void read(int &x)
{
    char c; int f=1;
    while(!((c=getchar())>='0'&&c<='9')) if(c=='-') f=-1;
    x=c-'0';
    while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
    x*=f;
}
const int maxn = 510000;
const int maxb = 21;

int n,m,L,R,a[maxn];
ll s[maxn];
int mn[maxn][maxb];

int get_mn(int l,int r)
{
    ll re=LLONG_MAX; int pos;
    for(int i=maxb-1;i>=0;i--) if(r-(1<<i)+1>=l)
    {
        if(re>s[mn[r][i]]) pos=mn[r][i],re=s[pos];
        r-=1<<i;
    }
    return pos;
}

struct node
{
    ll c;
    int l,r,i,p;
    node(){}
    node(const ll _c,int _l,int _r,int _i,int _p){c=_c;l=_l;r=_r;i=_i;p=_p;}
};
bool operator <(node x,node y){return x.c<y.c;}
priority_queue<node>Q;

int main()
{
    read(n); read(m); read(L); read(R);
    for(int i=1;i<=n;i++) read(a[i]),s[i]=s[i-1]+(ll)a[i];

    for(int i=0;i<=n;i++) mn[i][0]=i;
    for(int j=1;j<maxb;j++)
    {
        for(int i=1;i<=n;i++) 
        {
            int la=i-(1<<j-1);
            if(la<0) { mn[i][j]=mn[i][j-1]; continue; }
            if(s[mn[i][j-1]]<s[mn[la][j-1]]) 
                mn[i][j]=mn[i][j-1];
            else mn[i][j]=mn[la][j-1];
        }
    }

    for(int i=L;i<=n;i++)
    {
        int l=max(0,i-R),r=i-L;
        int p=get_mn(l,r);
        node tmp=node(s[i]-s[p],l,r,i,p);
        Q.push(tmp);
    }

    ll ans=0;
    while(m--)
    {
        node x=Q.top(); Q.pop();
        ans+=x.c;
        int l=x.l,r=x.p-1,p=get_mn(l,r);
        if(l<=r) Q.push(node(s[x.i]-s[p],l,r,x.i,p));
        l=x.p+1,r=x.r,p=get_mn(l,r);
        if(l<=r) Q.push(node(s[x.i]-s[p],l,r,x.i,p));
    }
    printf("%lld\n",ans);

    return 0;
}
Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值