Loading [MathJax]/jax/element/mml/optable/GeneralPunctuation.js
Codeforces 1107G Vasya and Maximum Profit

Codeforces 1107G Vasya and Maximum Profit

题目链接

http://codeforces.com/contest/1107/problem/G

题目大意

n 个题,每选择一道题你会获得 a 的收益,同时需要花费 c_i 才能获得第 i 道题。每道题的难度为 d_i ,令 gap(l, r) = \max\limits_{l \le i < r} (d_{i + 1} – d_i)^2 。你需要选择一段连续的题目,使得这些题目的净收益减去 gap(l, r) 最大。

题目分析

由于是连续的一段题目,所以可以考虑使用分治的思想,考虑一个区间分成两个子区间,则答案可能出现在两个子区间中,也可能横跨两个区间。在两个子区间的很好解决,递归求解即可,如果长度为 1 的话就直接返回 a – c_l 即可。

那么考虑横跨两个区间的情况,显然可知,起点一样的 gap 在长度增长的同时一定也是递增的,因此可以分成两种情况讨论,左区间的 gap 大于或者小于右区间的 gap,简单合并即可。

官方题解还给出了线段树的做法,将所有相邻点的 gap 从小到大排序,依次将它们添加至线段树中,维护最大连续子序列即可,想法也十分的巧妙。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 3e5 + 5;
long long n, m;
long long c[maxn];
long long d[maxn];
long long ans = 0;
int read(){
int x;
scanf("%d", &x);
return x;
}
long long sqr(long long x){
return x * x;
}
int dfs(int l, int r){
int mid = (l + r) / 2;
int i, j;
if(l == r){
ans = max(ans, m - c[l]);
}else{
dfs(l, mid);
dfs(mid + 1, r);
vector <long long> a[2];
vector <long long> b[2];
a[0].resize(mid - l + 1);
a[1].resize(mid - l + 1);
b[0].resize(r - mid);
b[1].resize(r - mid);
a[0][0] = m - c[mid];
a[1][0] = d[mid + 1] - d[mid];
for(i=1;i<mid-l+1;i++){
a[0][i] = a[0][i - 1] + m - c[mid - i];
a[1][i] = max(a[1][i - 1], d[mid - i + 1] - d[mid - i]);
}
b[0][0] = m - c[mid + 1];
b[1][0] = d[mid + 1] - d[mid];
for(i=1;i<r-mid;i++){
b[0][i] = b[0][i - 1] + m - c[mid + i + 1];
b[1][i] = max(b[1][i - 1], d[mid + i + 1] - d[mid + i]);
}
i = 0, j = 0;
long long maxa = a[0][0], maxb = b[0][0];
while(i < mid - l + 1){
maxa = max(maxa, a[0][i]);
while(j + 1 < r - mid and b[1][j + 1] <= a[1][i]){
j++;
maxb = max(maxb, b[0][j]);
}
ans = max(ans, maxa + maxb - sqr(a[1][i]));
i++;
}
i = 0, j = 0;
maxa = a[0][0], maxb = b[0][0];
while(j < r - mid){
maxb = max(maxb, b[0][j]);
while(i + 1 < mid - l + 1 and a[1][i + 1] <= b[1][j]){
i++;
maxa = max(maxa, a[0][i]);
}
ans = max(ans, maxa + maxb - sqr(b[1][j]));
j++;
}
}
return 0;
}
int main(){
int i, j;
n = read();
m = read();
for(i=1;i<=n;i++){
d[i] = read();
c[i] = read();
}
dfs(1, n);
printf("%lld\n", ans);
return 0;
}
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <vector> using namespace std; const int maxn = 3e5 + 5; long long n, m; long long c[maxn]; long long d[maxn]; long long ans = 0; int read(){ int x; scanf("%d", &x); return x; } long long sqr(long long x){ return x * x; } int dfs(int l, int r){ int mid = (l + r) / 2; int i, j; if(l == r){ ans = max(ans, m - c[l]); }else{ dfs(l, mid); dfs(mid + 1, r); vector <long long> a[2]; vector <long long> b[2]; a[0].resize(mid - l + 1); a[1].resize(mid - l + 1); b[0].resize(r - mid); b[1].resize(r - mid); a[0][0] = m - c[mid]; a[1][0] = d[mid + 1] - d[mid]; for(i=1;i<mid-l+1;i++){ a[0][i] = a[0][i - 1] + m - c[mid - i]; a[1][i] = max(a[1][i - 1], d[mid - i + 1] - d[mid - i]); } b[0][0] = m - c[mid + 1]; b[1][0] = d[mid + 1] - d[mid]; for(i=1;i<r-mid;i++){ b[0][i] = b[0][i - 1] + m - c[mid + i + 1]; b[1][i] = max(b[1][i - 1], d[mid + i + 1] - d[mid + i]); } i = 0, j = 0; long long maxa = a[0][0], maxb = b[0][0]; while(i < mid - l + 1){ maxa = max(maxa, a[0][i]); while(j + 1 < r - mid and b[1][j + 1] <= a[1][i]){ j++; maxb = max(maxb, b[0][j]); } ans = max(ans, maxa + maxb - sqr(a[1][i])); i++; } i = 0, j = 0; maxa = a[0][0], maxb = b[0][0]; while(j < r - mid){ maxb = max(maxb, b[0][j]); while(i + 1 < mid - l + 1 and a[1][i + 1] <= b[1][j]){ i++; maxa = max(maxa, a[0][i]); } ans = max(ans, maxa + maxb - sqr(b[1][j])); j++; } } return 0; } int main(){ int i, j; n = read(); m = read(); for(i=1;i<=n;i++){ d[i] = read(); c[i] = read(); } dfs(1, n); printf("%lld\n", ans); return 0; }
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

const int maxn = 3e5 + 5;

long long n, m;

long long c[maxn];
long long d[maxn];

long long ans = 0;

int read(){
	int x;
	scanf("%d", &x);
	return x;
}

long long sqr(long long x){
	return x * x;
}

int dfs(int l, int r){
	int mid = (l + r) / 2;
	int i, j;
	
	if(l == r){
		ans = max(ans, m - c[l]);
	}else{
		dfs(l, mid);
		dfs(mid + 1, r);
		vector <long long> a[2];
		vector <long long> b[2];
		
		a[0].resize(mid - l + 1);
		a[1].resize(mid - l + 1);
		b[0].resize(r - mid);
		b[1].resize(r - mid);
		
		a[0][0] = m - c[mid];
		a[1][0] = d[mid + 1] - d[mid];
		for(i=1;i<mid-l+1;i++){
			a[0][i] = a[0][i - 1] + m - c[mid - i];
			a[1][i] = max(a[1][i - 1], d[mid - i + 1] - d[mid - i]);
		}
		b[0][0] = m - c[mid + 1];
		b[1][0] = d[mid + 1] - d[mid];
		for(i=1;i<r-mid;i++){
			b[0][i] = b[0][i - 1] + m - c[mid + i + 1];
			b[1][i] = max(b[1][i - 1], d[mid + i + 1] - d[mid + i]);
		}
		
		i = 0, j = 0;
		long long maxa = a[0][0], maxb = b[0][0];
		
		while(i < mid - l + 1){
			 maxa = max(maxa, a[0][i]);
			 
			 while(j + 1 < r - mid and b[1][j + 1] <= a[1][i]){
			 	j++;
			 	maxb = max(maxb, b[0][j]);
			 }
			 
			 ans = max(ans, maxa + maxb - sqr(a[1][i]));
			 i++;
		}
		
		i = 0, j = 0;
		maxa = a[0][0], maxb = b[0][0];
		
		while(j < r - mid){
			 maxb = max(maxb, b[0][j]);
			 
			 while(i + 1 < mid - l + 1 and a[1][i + 1] <= b[1][j]){
			 	i++;
			 	maxa = max(maxa, a[0][i]);
			 }
			 
			 ans = max(ans, maxa + maxb - sqr(b[1][j]));
			 j++;
		}
	}
	
	
	return 0;
}

int main(){
	int i, j;
	
	n = read();
	m = read();
	
	for(i=1;i<=n;i++){
		d[i] = read();
		c[i] = read();
	}
	
	dfs(1, n);
	
	printf("%lld\n", ans);
	
	return 0;
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据