首页 > 其他分享 >P2048 超级钢琴 题解

P2048 超级钢琴 题解

时间:2023-06-05 13:33:53浏览次数:40  
标签:log int 题解 sum 钢琴 define 区间 include P2048

超级钢琴

题目大意

求出序列中长度在 \([L,R]\) 中的所有区间的区间和前 \(k\) 大的区间的区间和。

思路分析

暴力做法是把所有符合条件的区间扔进堆里,再弹出 \(k\) 个,时间复杂度 \(O((n^2+k)\log n)\),可以拿到 \(20\text{pts}\) 的好成绩。

但真的有必要全部加进去吗?不!

我们设五元组 \((l,r,x,y,w)\) 表示所有左端点在 \(x\),右端点在 \([l,r]\) 之间的区间和最大的区间的右端点为 \(y\),区间和为 \(w\)。

不难发现,如果 \(l,r,x\) 都是确定的,那么 \(y,w\) 也是确定的,即:

  • \(y\) 为区间 \([l,r]\) 内的最大的前缀和对应的下标。

  • \(w\) 可以通过 \(sum[y]-sum[x-1]\) 得到。

所以我们可以用线段树维护前缀和,\(O(\log n)\) 得到 \(l,r,x\) 对应的 \(y,w\),所以 \((l,r,x)+O(\log n)=(l,r,x,y,w)\)。

那么我们开始时只需要将所有的 \((i+L-1,i+R-1,i),1\le i\le n-L+1\) 加入一个按 \(w\) 比较的大根堆,在弹出第一个即为所有符合条件的区间的最大值。

那其他的次大值呢?

不难发现,我们的最大值是通过 \(y\) 得到的,因此,只要我们把 \(y\) 扣掉,再插入堆,就可以得到次大值。

具体的说,当我们的堆顶是 \((l,r,x)\) 时,我们弹出堆顶,将 \(w\) 加入答案,并将 \((l,y-1,x)\) 和 \((y+1,r,x)\) 加入堆。

只需要重复上述过程 \(k\) 次就可以得到全部答案。

时间复杂度 \(O((n+k)\log n)\)。

代码

#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;
const int N=500500;
#define int long long
#define PII pair<long long,long long>
#define mid (l+r>>1)
#define inf 0x3f3f3f3f3f3f3f3f

int n,k,L,R,ans;
int inp[N],sum[N];

struct Node{
    int l,r,x,y,val;
}now;

bool operator < (Node a,Node b){
    return a.val<b.val;
}

priority_queue <Node> q;

struct ST{
    int maxn[N<<2],maxi[N<<2];
    void build(int p,int l,int r){
        if(l==r){maxn[p]=sum[l];maxi[p]=l;return ;}
        build(p<<1,l,mid);build(p<<1|1,mid+1,r);
        maxn[p]=max(maxn[p<<1],maxn[p<<1|1]);
        maxi[p]=(maxn[p<<1]==maxn[p])?maxi[p<<1]:maxi[p<<1|1];
    }
    PII ask(int p,int l,int r,int x,int y){
        if(x<=l&&r<=y) return {maxn[p],maxi[p]};
        PII ls=(x<=mid)?ask(p<<1,l,mid,x,y):PII{-inf,-inf};
        PII rs=(y>mid)?ask(p<<1|1,mid+1,r,x,y):PII{-inf,-inf};
        return max(ls,rs);
    }
}tree;

void insert(int l,int r,int x){
    int maxi=tree.ask(1,1,n,l,r).second;
    q.push(Node{l,r,x,maxi,sum[maxi]-sum[x-1]});
}

signed main(){
    scanf("%lld%lld%lld%lld",&n,&k,&L,&R);
    for(int i=1;i<=n;i++)
        scanf("%lld",&inp[i]),sum[i]=sum[i-1]+inp[i];
    tree.build(1,1,n);
    for(int i=1;i<=n;i++)
        if(i+L-1<=n) insert(i+L-1,min(i+R-1,n),i);
    for(int i=1;i<=k;i++){
        if(q.empty()) break;
        now=q.top();q.pop();
        ans+=now.val;
        if(now.y!=now.r) insert(now.y+1,now.r,now.x);
        if(now.y!=now.l) insert(now.l,now.y-1,now.x);
    }
    cout<<ans<<'\n';
    return 0;
}

标签:log,int,题解,sum,钢琴,define,区间,include,P2048
From: https://www.cnblogs.com/TKXZ133/p/17457562.html

相关文章

  • P5445 路灯 题解
    路灯题目大意在\(n+1\)个站点之间有\(n\)盏路灯,给定\(0\)时刻所有路灯的亮灭情况,在接下来的\(q\)个时刻,每时刻会发生以下两种事件之一:切换某一盏路灯的亮灭。询问两点之间存在多少时刻使得两点之间的路灯全部亮起。思路分析一道不错的数据结构。首先分析题目......
  • Mysql 主从备份 Last_Errno: 1146 Last_Error: Error executing row event: 错误问题
    本人在做主从备份的时候发现了此问题! 1主数据库是已经把这个表删除了丛数据库也是没有备份这个表但是一直报这个错原因是bin-log日志有这个表 但是没记录到已经把这个表删除了 主从表同步实际从库是根据主库的bin-log二进制的SQL进行执行的 这是Mysql的一个BUG1......
  • erlang实现长连接管理问题解决
    具体参见:http://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-1/1.    erlang进程增加了休眠特性hibernate,支持连接从20w->70w;如上面的文章里面所说,使用hibernate后支撑的长连接飞涨。2.    40w时系统出现异常。查看系统日志发现socket......
  • CF1818D 题解
    一、题目描述:给你一颗$n$个点,$m$条边的简单无向图,可能不连通。我们定义$鱼图$为满足以下条件的无向图:$包含恰好\1\个环,环上有\1\个特殊的结点\u\,u\除了连在环上的\2\条边外还正好有\2\条边连向不在此环上的结点。$求是否存$鱼图$。若存......
  • 题解
    原题请见题目链接1.暴力求解这是我们线下水题赛的T1这里为初学者提供一个思路,假设我们现在刚入OI,在考场上如何怎么优雅的避免保灵显然我们只要用一个\(O(n)\)的暴力去扫描就行了,但是直接向后扫\(i+1,i+2\)这样走很容易寄。因为你在\(i+1\)跳的时候很容易把后面跳过了......
  • 【题解】[ABC304F] Shift Table(容斥)
    【题解】[ABC304F]ShiftTable题目链接ABC304F题意概述Takahashi和Aoki将在接下来的\(N\)天里兼职工作。Takahashi这\(n\)天的出勤情况由字符串\(S\)表示,其中\(S\)的第\(i\)个字符是#则表示他在第\(i\)天工作,第\(i\)个字符是.表示他在第\(i\)天休息......
  • 题解:【AGC054D】 (ox)
    题目链接Larry76牛牛首先考虑没有ox怎么做,就是将括号序列调成合法。\(|S|\)不大直接模拟一遍,记录\(now\)表示一个前缀权值,当遇到一个(时\(+1\),遇到一个)时\(-1\),当\(now<0\)的时候说明序列不合法即)多了,暴力向后找到第一个(交换到当前的)前面。这样我们......
  • Codeforces Round 876 (Div. 2)题解
    CodeforcesRound876(Div.2)A.TheGoodArray标签greedymath题意对于任意\(i\in\{1,2,\dots,n\}\),要求数列\(a\)满足前\(i\)个元素中至少有\(\lceil\frac{i}{k}\rceil\)个元素为\(1\),后\(i\)个元素中至少有\(\lceil\frac{i}{k}\rceil\)个元素为\(1\)。思......
  • “AIR SDK 0.0: AIR SDK location “...\devsdks\AIRSDK\Win” does not exist.”
    导入AS3项目时提示“AIRSDK0.0:AIRSDKlocation“D:\ProgramFiles\Adob5eFlashBuilder4.7\eclipse\plugins\com.adobe.flexbuilder.flex_4.7.0.349722\devsdks\AIRSDK\Win”doesnotexist.”是AS3项目找不见AIRSDK.打开项目配置ActionScriptBuildPath,路径出错......
  • CF1329E Dreamoon Loves AA 题解
    令\(p_0=0,m\leftarrowm+1,p_{m}=n,a_i=p_i-p_{i-1}\),设在\((p_{i-1},p_i)\)中有\(d_i-1\)个B变成了A,满足\(\sum_{i=1}^m(d_i-1)=k\),让\(k\leftarrowk+m\),这样\(d\)需要满足的限制就变成了\(\sum_{i=1}^md_i=k\)。这也可以看作把\(a_i\)分成\(d_i\)个正整数之......