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

【题解 P2048】 超级钢琴

时间:2023-11-15 10:25:29浏览次数:36  
标签:和弦 度为 int 题解 超级 钢琴 美妙 音符 P2048

[NOI2010] 超级钢琴

题目描述

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

这架超级钢琴可以弹奏出 \(n\) 个音符,编号为 \(1\) 至 \(n\)。第 \(i\) 个音符的美妙度为 \(A_i\),其中 \(A_i\) 可正可负。

一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于 \(L\) 且不多于 \(R\)。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。

小 Z 决定创作一首由 \(k\) 个超级和弦组成的乐曲,为了使得乐曲更加动听,小 Z 要求该乐曲由 \(k\) 个不同的超级和弦组成。我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小 Z 想知道他能够创作出来的乐曲美妙度最大值是多少。

输入格式

输入第一行包含四个正整数 \(n, k, L, R\)。其中 \(n\) 为音符的个数,\(k\) 为乐曲所包含的超级和弦个数,\(L\) 和 \(R\) 分别是超级和弦所包含音符个数的下限和上限。

接下来 \(n\) 行,每行包含一个整数 \(A_i\),表示按编号从小到大每个音符的美妙度。

输出格式

输出只有一个整数,表示乐曲美妙度的最大值。

样例 #1

样例输入 #1

4 3 2 3
3
2
-6
8

样例输出 #1

11

提示

样例解释

共有 \(5\) 种不同的超级和弦:

  1. 音符 \(1 \sim 2\),美妙度为 \(3+2=5\);
  2. 音符 \(2 \sim 3\),美妙度为 \(2+(-6)=-4\);
  3. 音符 \(3 \sim 4\),美妙度为 \((-6)+8=2\);
  4. 音符 \(1 \sim 3\),美妙度为 \(3+2+(-6)=-1\);
  5. 音符 \(2 \sim 4\),美妙度为 \(2+(-6)+8=4\)。

最优方案为:乐曲由和弦 \(1,3,5\) 组成,美妙度为 \(5+2+4=11\)。

所有数据满足:\(-1000 \leq A_i \leq 1000\),\(1 \leq L \leq R \leq n\) 且保证一定存在满足要求的乐曲。

解题思路

题意简述就是要我们选出 \(k\) 个长度 \(l\) 在 \([L,R]\) 之间的区间,每个区间的贡献是内部数的总和,要总贡献最大。
由于有区间和,我们就可以用前缀和。
对于一个左端点为 \(l\) ,右端点为 \(r\) 的区间,它的贡献就位 \(a_r-a_{l-1}\) 。
由于有长度限制,我们可以固定住左端点为 \(l\) ,那么右端点 \(r\) 的范围就是 \([l+L-1,min(l+R-1,n)]\) 。
由于 \(l\) 不变,\(a_{l-1}\) 也不变,我们只需找出使 \(a_x\) 最小且在 \([l+L-1,min(l+R-1,n)]\) 之间的 \(x\) 即可。
那我们就可以开一个 \(ST\) 表维护 \([l+L-1,min(l+R-1,n)]\) 内的最大值,把每一个 \(l\) 以及它的右端点范围开一个结构体,丢到一个堆里面,每次贪心取最大即可。
每次取出来后,把它分裂为两部分,即分裂成 \((l,i+l-1,x-1)\) 与 \((l,x+1,min(l+R-1,n))\) ,在丢进堆即可。
每次累加答案,即可求最大值。
\(ST\) 表查询时间 \(O(1)\) ,总时间复杂度 \(O(nlogn)\) 。

Code

#include<bits/stdc++.h>
using namespace std;
struct datay
{
	int x,y,z; 
	datay(int q,int w,int e)
	{
		x=q;
		y=w;
		z=e;
	}
};
long long n,a[500005],l[500005],p[500005],L,R,k,s;
int f[500005][21],z;
int gaia(int ll,int rr)
{
	z=l[rr-ll+1];
	return (a[f[ll][z]]>a[f[rr-p[z]+1][z]])?f[ll][z]:f[rr-p[z]+1][z];
}
bool operator <(const datay &q,const datay &w)
{
	return (a[gaia(q.y,q.z)]-a[q.x])<(a[gaia(w.y,w.z)])-a[w.x];
}
priority_queue<datay> t;
int main()
{
	datay q=datay(0,0,0);
	int x;
	scanf("%lld%lld%lld%lld",&n,&k,&L,&R);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]),f[i][0]=i,a[i]+=a[i-1];
	l[0]=-1,p[0]=1;
	for(int i=1;i<=n;i++)l[i]=l[i/2]+1;
	for(int i=1;i<=20;i++)p[i]=p[i-1]*2;
	for(int i=1;i<=20;i++)
	{
		for(int j=1;j+p[i]-1<=n;j++)
		{
			if(a[f[j][i-1]]>a[f[j+p[i-1]][i-1]])f[j][i]=f[j][i-1];
			else f[j][i]=f[j+p[i-1]][i-1];
		}
	}
	for(int i=1;i<=n-L+1;i++)
	{
		t.push(datay(i-1,i+L-1,min(n,i+R-1)));
	}
	for(int i=1;i<=k;i++)
	{
		q=t.top();
		x=gaia(q.y,q.z);
		s+=(a[x]-a[q.x]);
		t.pop();
		if(x!=q.y)t.push(datay(q.x,q.y,x-1));
		if(x!=q.z)t.push(datay(q.x,x+1,q.z));
	}
	cout<<s;









  return 0;
}

标签:和弦,度为,int,题解,超级,钢琴,美妙,音符,P2048
From: https://www.cnblogs.com/dijah/p/17833237.html

相关文章

  • Linux openssh问题解决: Permission denied, please try again
    1.vim打开sshd_config文件vim/etc/ssh/sshd_config2.搜索PermitRootLogin ,将 PermitRootLoginprohibie-password 改为如下:PermitRootLoginyes  ......
  • 洛谷 P1931 题解
    三倍经验P1931UVA436SP9340题意给你\(n(n\le30)\)种货币及\(m\)种汇率,问是否出现套利的情况。怎么没给\(m\)的范围啊思路首先把汇率抽象成一张图。容易发现,若一个单位的某种货币经过一个环获得了大于一的代价,说明出现了套利。具体来说,考虑Floyd,若$\existsi\in......
  • CF1542E2 Abnormal Permutation Pairs (hard version) 题解
    怎么会有这么离谱的题目啊。【模板】前缀和优化dp。思路考虑一个基本的东西。由于要求字典序的限制。我们可以枚举最长公共前缀计算。考虑如何求长度为\(i\)的排列有\(j\)个逆序对的数量。设\(dp_{i,j}\)。\[dp_{i,j}=\sum_{k=0}^{i-1}dp_{i-1,j-k}\]就是枚举新的......
  • [题解] CF1051F The Shortest Statement
    TheShortestStatement给一张\(n\)个点\(m\)条边的无向连通图,保证\(m-n\le20\),\(q\)次询问求两个点间的最短路。\(n,m,q\le10^5\)。由于边数只比点数多20,所以如果我们建出这张图的一棵生成树,那么非树边至多有21条。那么现在两点之间的最短路就转化成了不......
  • 「NOIP2014」解方程 题解
    思路首先我们可以观察到\(n\)和\(m\)与\(a_i\)相比小的很多,所以我们可以考虑直接暴力求解但是\(a_i\)太大了,所以如果需要直接计算的话需要全程使用高精度算法。因为高精度算法代码量有大速度又慢我们可依考虑将\(a_i\)转化为一个极大的指数取模的结果,因为只有是模数的......
  • Q7.4.1.2. 奇怪的方格涂色 题解
    原题链接首先想到暴力网络流:考虑最小割,\(S\)表示染黑色,\(T\)表示染白色。每个格子\(i\),连\((S,i,b_i)\),\((i,T,w_i)\)。怎么处理“奇怪的方格”?连\((i,i^\prime,p_i)\)和\((i^\prime,j,+\infty)\)。表示如果\(i\)归属于\(S\)(染黑色),那么就只能忍受奇怪所带来的\(p_i\)......
  • AT_abc230_f [ABC230F] Predilection 题解
    prelogue各位在比赛的时候一定要坚信自己的式子,然后去考虑自己的实现是不是挂了。本人在今天模拟赛的时候质疑自己的式子然后不看实现100->0。analysis考虑对这个给定数组进行前缀和,然后就将问题转化成为了求这个前缀和数组的子序列的个数。对于求子序列,我们很轻松可以写出......
  • Codeforces Round 809 (Div. 2) D1. Chopping Carrots (Easy Version) 题解
    题意CodeforcesRound809(Div.2)D1.ChoppingCarrots(EasyVersion)给两个整数\(n,k\),一个数组\(a\),要求构造一个同样长度的数组\(p\),使得\(\max\limits_{1\lei\len}\left(\left\lfloor\frac{a_i}{p_i}\right\rfloor\right)-\min\limits_{1\lei\l......
  • [USACO23FEB] Equal Sum Subarrays G 题解
    [USACO23FEB]EqualSumSubarraysG题解题目链接\(O(n^5)\)暴力显然,如果修改\(a_i\)的值,只会影响包含\(a_i\)的区间的区间和。于是对于每个\(a_i\),可以将所有区间分成两类,即包含\(a_i\)的区间和不包含\(a_i\)的区间。这两种区间的区间和中最小的差值即为答案。......
  • 【洛谷 P1307】[NOIP2011 普及组] 数字反转 题解(字符串)
    [NOIP2011普及组]数字反转题目描述给定一个整数,请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零(参见样例2)。输入格式一个整数。输出格式一个整数,表示反转后的新数。样例#1样例输入#1123样......