BZOJ2298: [HAOI2011]problem a

这题长得很邪乎,表示一眼啥也看不出来

然而是在讲 dp 的课件上看到的,依然看不出来是 dp

于是去颓题解

大概是没往这个模型方面想

我们把一个人说的话用线段表示出来

线段左右端点分别为 : ai + 1, n - bi

表示这一段人分数相同

若有相交或包含的线段那其中必然矛盾

完全相等的线段我们将其合并, 并将线段的权值 + 1

线段的权值不能大于线段长度,因为不会有超过线段长度的人考同一个分数

从样例也可以看出来,线段左端点不能大于右端点 或 ai + bi <= n

枚举一个右端点,用所有以当前点为右端点的线段和当前线段左端点 -1 的位置的 f值 更新 f[i]


 

代码:

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#include<map>
using namespace std;

const int MAXN = 100005;

int n;
int f[MAXN];
map<pair<int,int>, int> mp;
vector<int> seg[MAXN];

int main() {
	scanf("%d", &n);
	register int xx, yy;
	pair<int, int> dst;
	for(int i = 1; i <= n; ++i) {
		scanf("%d%d", &xx, &yy);
		xx += 1;
		yy = n - yy;
		if(xx > yy) continue;
		dst = make_pair(xx, yy);
		mp[dst] = ((mp[dst] == yy - xx + 1) ? (mp[dst]) : (mp[dst] + 1));
		if(mp[make_pair(xx, yy)] == 1) seg[yy].push_back(xx); 
	}
	for(int i = 1; i <= n; ++i) {
		f[i] = f[i - 1];
		for(int j = 0; j < seg[i].size(); ++j) {
			f[i] = max(f[i], f[seg[i][j] - 1] + mp[make_pair(seg[i][j], i)]);
		}
	}
	printf("%d\n", n - f[n]);
	return 0;
}

 STL常数大

posted @ 2018-08-22 18:21  EvalonXing  阅读(164)  评论(0编辑  收藏  举报