JZOJ 5350. 【NOIP2017提高A组模拟9.7】陶陶摘苹果

题目

分析

很神奇的事情又发生了!!
很容易想到设 (f_{i,j}) 表示考虑前 (i) 个区间,已选 (j) 个区间且必选第 (i) 时能覆盖到的最多苹果数
转移 (O(n)) 很显然了
然后,就没了·····
什么?!!
实际上测试数据给的答案是不能不用凳子的!!!
于是悲剧了······

(Code)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 1e6 + 5 , M = 205;
int n , m , h , k , ans , fi , s[N] , f[M][M];
struct node{
	int l , r;
}g[M];
bool cmp(node a , node b){return a.l < b.l ? 1 : (a.l == b.l ? a.r < b.r : 0);}

int main()
{
	freopen("apple.in" , "r" , stdin);
	freopen("apple.out" , "w" , stdout);
	scanf("%d%d%d%d" , &n , &m , &h , &k);
	int x , Mx = 0;
	for(register int i = 1; i <= n; i++)
	{
		scanf("%d" , &x);
		if (x == h) {fi++; continue;}
		if (x < h) continue;
		s[x - h]++;
	}
	for(register int i = 1; i <= m; i++) 
		scanf("%d%d" , &g[i].l , &g[i].r) , Mx = max(Mx , g[i].r);
	sort(g + 1 , g + m + 1 , cmp);
	memset(f , -0x3f3f , sizeof f);
	for(register int i = 1; i <= Mx; i++) s[i] += s[i - 1];
	for(register int i = 1; i <= m; i++)
	{
		f[i][0] = 0 , f[i][1] = s[g[i].r] - s[g[i].l - 1];
		for(register int j = 2; j <= min(i , k); j++)
			for(register int l = 1; l < i; l++)
			{
				if (f[l][j - 1] < 0) continue;
				int sum = s[g[i].r];
				if (g[l].r >= g[i].l) sum -= s[g[l].r];
				else sum -= s[g[i].l - 1];
				f[i][j] = max(f[i][j] , f[l][j - 1] + sum);
			}
	}
	for(register int i = k; i <= m; i++) ans = max(ans , f[i][k]);
	printf("%d" , ans);
}
原文地址:https://www.cnblogs.com/leiyuanze/p/13774232.html