首页 > 其他分享 >P2048 [NOI2010] 超级钢琴

P2048 [NOI2010] 超级钢琴

时间:2024-09-06 11:37:09浏览次数:10  
标签:idx int ll tp st 钢琴 NOI2010 P2048

P2048 [NOI2010] 超级钢琴

题目链接

其实这道题在我刚学 oi 两个月 (2023.3) 就见过了

当时是作为 st 表的一个例题出现的, 我学 st 表就已经学得迷迷糊糊的了, 更别说这题了哈哈

所以这是第二次见到他, 必须写了(这一次他是作为 NOIP 模拟赛的一个部分分做法出现的)

思路

不错的限制:每个和弦都是连续的

所以可以考虑一个基于起点位置的贪心

按照常规的思路 \(idx, p, v\) 表示以 \(idx\) 为起点, 向后延伸到了 \(p\) 位置, 当前位置的贡献为 \(v\)

然后把他们丢进优先队列, 每次取堆顶, 把 \(p\) 向后延伸一位即可

但是

这个序列不是单调的, 因为中间有一些负数

这就意味着距离 \(idx\) 为 \(R\) 的点到 \(idx\) 的这段序列并不一定是最大的

所以上述做法只能用于一个削弱版的本题

该如何改进呢

其实并不难, 但是我一开始没想出来

设 \([l, r]\ \ \ idx \ \ \ v\) 表示当前可选的右端点在区间 \([l, r]\) 中, 其中取到最大值的是下标为 \(idx\) 的右端点, 贡献为 \(v\)

这样, 每次取完堆顶后, \([l, r]\) 就分成了 \([l, idx - 1]\) 和 \([idx + 1, r]\) 两个区间, 对这两个区间再分别算出 \(v\) 和 \(idx\) 即可

这一步可以用 st 表实现, 是 \(O(1)\)

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

代码

#include <bits/stdc++.h>
#define int long long
// #pragma GCC optimize(2)
using namespace std;
const int N = 5e5 + 10, Base = 191;

int n, k, l, r;
int a[N];
int st[20][N], ps[20][N];

void Init(){
	for(int i = 1; i < 20; i++){
		for(int j = 0; j + (1 << i) - 1 <= n; j++){
			if(st[i - 1][j] > st[i - 1][j + (1 << (i - 1))]){
				st[i][j] = st[i - 1][j];
				ps[i][j] = ps[i - 1][j];
			}else{
				st[i][j] = st[i - 1][j + (1 << (i - 1))];
				ps[i][j] = ps[i - 1][j + (1 << (i - 1))];
			}
		}
	}
}

struct Ret{
	int maxi, maxid;
};

Ret Query(int l, int r){
	int k = __lg(r - l + 1);

	Ret ret = {0, 0};
	if(st[k][l] > st[k][r - (1 << k) + 1]){
		ret.maxi = st[k][l];
		ret.maxid = ps[k][l];
	}else{
		ret.maxi = st[k][r - (1 << k) + 1];
		ret.maxid = ps[k][r - (1 << k) + 1];		
	}
	return ret;
}

struct Node{
	int idx, l, r, mid, v;

	bool operator < (const Node &p)const{
		return v < p.v;
	}
}tp;
priority_queue <Node> q;

signed main(){
	// freopen("1.in", "r", stdin);

	cin >> n >> k >> l >> r;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
		st[0][i] = st[0][i - 1] + a[i];
		ps[0][i] = i;
	}

	Init();
	for(int i = 1; i + l - 1 <= n; i++){
		int ll = i + l - 1, rr = min(i + r - 1, n);
		auto ret = Query(ll, rr);
		q.push({i, ll, rr, ret.maxid, ret.maxi - st[0][i - 1]});
	}

	int sum = 0;
	for(int i = 1; i <= k; i++){
		tp = q.top();
		q.pop();

		sum += tp.v;
		if(tp.mid - 1 >= tp.l){
			int ll = tp.l, rr = tp.mid - 1;
			auto ret = Query(ll, rr);
			q.push({tp.idx, ll, rr, ret.maxid, ret.maxi - st[0][tp.idx - 1]});
		}
		if(tp.mid + 1 <= tp.r){
			int ll = tp.mid + 1, rr = tp.r;
			auto ret = Query(ll, rr);
			q.push({tp.idx, ll, rr, ret.maxid, ret.maxi - st[0][tp.idx - 1]});
		}
	}
	cout << sum << "\n";
}

标签:idx,int,ll,tp,st,钢琴,NOI2010,P2048
From: https://www.cnblogs.com/Bubblee/p/18399934

相关文章

  • c语言编译器IDE的6键钢琴程序代码
    #include<stdio.h>#include<SDL2/SDL.h>#include<SDL2/SDL_mixer.h>//FunctionforloadingmusictoMix_MusicstaticMix_Music*loadMusic(constchar*path){Mix_Music*music=Mix_LoadMUS(path);if(music==NULL){fprintf(stderr,“M......
  • c语言编译器IDE小钢琴程序代码
    #include<stdio.h>#include<SDL2/SDL.h>#include<SDL2/SDL_mixer.h>//FunctionforloadingmusictoMix_MusicstaticMix_Music*loadMusic(constchar*path){Mix_Music*music=Mix_LoadMUS(path);if(music==NULL){fprintf(stderr,“M......
  • vb6.0版本钢琴简谱播放程序代码QZQ-2024-8-30
    OptionExplicitConstINVALID_NOTE=-1’Codeforkeyboardkeysthatwedon’thandleDimnumDevicesAsLong’numberofmidioutputdevicesDimcurDeviceAsLong’currentmidideviceDimhmidiAsLong’midioutputhandleDimrcAsLong’return......
  • VB版本MIDI钢琴简谱播放器全代码QZQ-2024-8-30
    PrivateDeclareFunctionGetKeyState%Lib“user32”(ByValnVirtKeyAsLong)PrivateDeclareSubSleepLib“kernel32”(ByValdwMillisecondsAsLong)PrivatesuduAsIntegerPrivateConstVK_LBUTTON&=&H1PrivateisOgainAsBoolean'是否重复按键Pri......
  • 【题解】P3210 [HNOI2010] 取石头游戏
    \(\large\mathfrak{1st.\Preamble|}\)前言题目传送门:P3210[HNOI2010]取石头游戏)主要是参考楼下大佬的题解,对于其中没讲到或比较难懂的地方进行讲解,以及配上了图。\(\large\mathfrak{2nd.\Solution|}\)题解楼下大佬的比喻十分形象生动地描绘了俩人去石头的过程:取石子......
  • P2048 [NOI2010] 超级钢琴
    题意在一个数组中选择\(k\)个长度为\([l,r]\)的序列,对每个序列求和,使每个序列的和的和最大。思路首先,我们可以将序列之和转化为前缀和,如果固定左端点\(l\),那么我们只需要在\([l+len_l,l+len_r]\)中寻找最大的右端点,减去\(sum[l-1]\)就是在长度为\([len_l,le......
  • VB.NET钢琴MIDI简谱播放器代码QZQ2024-8-7
    ImportsSystem.Runtime.InteropServicesPublicClassForm1'义WindowsAPI函数<DllImport(“winmm.dll”)>PrivateSharedFunctionmidiOutGetNumDevs()AsIntegerEndFunction<DllImport("winmm.dll")>PrivateSharedFunctionmidiOutGet......
  • D39 2-SAT P3209 [HNOI2010] 平面图判定
    视频链接:D392-SATP3209[HNOI2010]平面图判定_哔哩哔哩_bilibili   图论(十三)——平面图和对偶图_图论(十三)——平面图和对偶图-CSDN博客P3209[HNOI2010]平面图判定-洛谷|计算机科学教育新生态(luogu.com.cn)#include<iostream>#include<cstring>#incl......
  • P1447 [NOI2010] 能量采集
    题目传送容斥思想的一道好题。题目容易转化为:\[2\times\sum_{i=1}^n\sum_{j=1}^n(\gcd(i,j))\-nm.\]直接求和不好求,不妨转换为枚举\(d=\gcd(i,j)\)。那么\(i,j\)应该均为\(d\)的倍数。记\(f(i)=\left\lfloor\frac{n}{i}\right\rfloor\cdot\left\lfloor......
  • Spectrasonics Keyscape v1.5.0c + Soundsource v1.6.0c,四巨头钢琴合成器,可以试试
    SpectrasonicsKeyscapev1.5.0c+Soundsourcev1.6.0c    KEYSCAPE是一款非凡的虚拟乐器,拥有世界上最多的收集器键盘选择。从“圣杯”钢琴到令人惊叹的键盘,你甚至不知道存在,这是一个键盘手的梦想成真。经过十年的制作,这些备受欢迎的键盘都经过精心修复,然后由著名的......